下面先介紹man
ache
rmanacher
manach
er演算法。假設str
strst
r為待處理字串,len
[i
]len[ i ]
len[i]
陣列存放以該str
[i
]str[ i ]
str[i]
字元為中心的最長回文半徑,mid
midmi
d為當前最長回文子串的中點,mxmx
mx為當前最長回文子串的右邊界.。
在開始演算法之前,先在字串中首部填充$,字元之間#。比如,字串abaaba填充之後就變成了$#a#b#a#a#b#a#($與#未在字串**現)。
那麼對當前位置 i
ii有如下偽**:(此時已經知道前i−1
i - 1
i−1個字元的最長回文半徑)
若i
i < mx i,則l en [i]= min( len[ 2×mi d−i] ,mx− i) len[ i ] = min ( len[ 2 \times mid - i ] , mx - i ) len[i] =min (len [2×m id−i ],mx −i)。 否則l en [i]= 1len[ i ] = 1 len[i] =1。對i ii位置上的字元向兩邊進行匹配,更新len [i ]len[ i ] len[i] 的值,更新結束後更新mid midmi d和mx mxmx 的值。 命題:如果i i < mx i,那麼i ii為中心的最長回文半徑最少為min (len [2×m id−i ],mx −i )min ( len[ 2 \times mid - i ] , mx - i ) min(le n[2× mid− i],m x−i) 。證明: 首先i i < mx i說明i ii坐落於以mid midmi d為中心的回文子串中。在該回文子串範圍內,左右兩邊是完全對稱的,所以i ii的最長回文半徑可參考其對稱點2×m id−i 2 \times mid - i 2×mid− i的最長回文半徑。 已知其對稱點2×m id−i 2 \times mid - i 2×mid− i最長回文半徑為min (len [2×m id−i ],mx −i )min ( len[ 2 \times mid - i ] , mx - i ) min(le n[2× mid− i],m x−i) ,所以i ii的最長回文半徑至少為min (len [2×m id−i ],mx −i )min ( len[ 2 \times mid - i ] , mx - i ) min(le n[2× mid− i],m x−i) ,超出mxmx mx的部分暴力匹配即可。 $#a#b#a#a#b#a#中以#為中心的最長回文子串去掉#後對應原字串的最長偶回文串,以原字元為中心的最長回文子串去掉#後對應原字串的最長奇回文串。而去掉#後的最長回文串的長度正好等於回文半徑減1 11,這樣問題轉化為了求$#a#b#a#a#b#a#的最長回文半徑。 由於每個字元只會被匹配一次,所以時間複雜度為o(n )\mathcal(n) o(n) 。 #include #include #include using namespace std; const int maxn= 110010 ;char s[maxn] ,ma[maxn*2] ;int mp[maxn*2] ;int manacher (char *s,int len) return res; }int main() return0; } 題 目 鏈 接 看完後自己寫了一遍,感覺真的是很神奇的結論啊!本來這題看到可以用字尾陣列來寫的,但沒有學過,去看了一下,真心給暈了,決定找個機會認真研究下。我的 include include includeusing namespace std define min a,b a b a b cha... 存在o n 的演算法,學習了一下 include include includeusing namespace std const int maxn 300011 int n,p maxn char str maxn in maxn int main str 0 str 1 n n 2 2 str ... problem description 給出乙個只由小寫英文本元a,b,c.y,z組成的字串s,求s中最長回文串的長度.回文就是正反讀都是一樣的字串,如aba,abba等 input 輸入有多組case,不超過120組,每組輸入為一行小寫英文本元a,b,c.y,z組成的字串s 兩組case之間由空行...#include
HDU 3068 最長回文
HDU 3068 最長回文
HDU 3068 最長回文