這題好像只能用mancher演算法解決,速成馬拉車演算法。
這個演算法的核心思想就是,如果當前要維護的下標i小於上一次經維護後的max值,我們就取上一次得到的對稱位置的回文半徑。
這個回文半徑就是min(p[ id * 2 - i] , max-i),它的意思就代表了,我們先取其中最小的乙個半徑,然後我們之後再暴力向後拓展。
因為我們下一步是暴力,所以我們上一步取乙個小值即可。括號中的兩個表示式的意思是,它的對稱位置 由 中心位置
id-(i-id) 得到,所以就取它對稱位置的回文半徑值,要麼就是上次拓展的最大位置減去i值,它們兩個中取乙個最小值,
這樣我們就不必暴搜之前的那麼多次了。我們只用搜尋之後的就可了。
但是在我們維護之前,我們可以看到,如果我們維護奇數長度的子串的時候,還是很方便的,所以當我們維護偶數長度的時候,我們就把偶數變奇數即可。
我們在每次字元之間加上乙個#,這樣的話,如果是偶數長度,中間就有奇數個間隙,左右兩邊共有兩個#,偶數加偶數加奇數,就是奇數。對於奇數長度同理。
然後我們求的這個陣列p裡面求的其實是半徑值,而我們之前把原子串擴充套件了1倍,所以而我們求的半徑值減一就是原子串的直徑。
這就是馬拉車演算法的思路,其實和kmp還是蠻像的。
#include
#include
const
int maxn =
3e5;
char s[maxn]
, str[maxn]
;int len1, len2, p[maxn]
, ans;
intmin
(int x,
int y)
void
init()
len2 = len1 *2+
2;str[len2]
='*';}
void
manacher()
}}intmain()
printf
("%d\n"
, ans-1)
;}}
HDU 3068 最長回文
題 目 鏈 接 看完後自己寫了一遍,感覺真的是很神奇的結論啊!本來這題看到可以用字尾陣列來寫的,但沒有學過,去看了一下,真心給暈了,決定找個機會認真研究下。我的 include include includeusing namespace std define min a,b a b a b cha...
HDU 3068 最長回文
存在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 ...
HDU 3068 最長回文
problem description 給出乙個只由小寫英文本元a,b,c.y,z組成的字串s,求s中最長回文串的長度.回文就是正反讀都是一樣的字串,如aba,abba等 input 輸入有多組case,不超過120組,每組輸入為一行小寫英文本元a,b,c.y,z組成的字串s 兩組case之間由空行...