簡介
abcba
abccba
從上面兩個簡單的字符串中可以看出——迴文串中心是不確定的:
奇數:有一個字符作爲迴文串中心;
偶數:有兩個字符作爲迴文串中心;
馬拉車採用了非常聰明的小辦法解決這個問題——往其中加入中間字符:
變成了(暫且忽略第一個’~'字符)——>
~a|b|c|b|a:迴文中心爲 ‘c’ 字符
~a|b|c|c|b|a:迴文中心爲 ‘|’ 字符
當然,你插入啥字符效果也差不多,看個人愛好
就hen神奇的變成了迴文中心只有一個字符了。
說明一下模板題變量的意義看大佬的blog,感覺這樣解釋好理解一點
cnt:插入字符後串的總長度
p[i] :以i爲中心的迴文串像某一邊最長延伸長度(如a|b|c|b|a,i=5時,相應的p[i]爲5)初始化爲1(字符本身是個迴文串)
mx:當前已判斷過的最長迴文串的長度
id:mx對應的迴文中心
ans:答案——最大的p[i]-1插入了其他字符,一邊的長度-1就是答案啦
當下標 以 爲中心對稱時, 可以由 推出, 同樣可以由 推出
當 ,即當前下標處於迴文串中,與下標 對稱的 滿足 。但是!!!要注意 一定是小於等於 ,即 ,兩者取下最小值就可以得到 啦
應用
題目
manacher模板題
代碼
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1.1e7+10;
char s[maxn<<1], c;
int p[maxn<<1], cnt, mx, id, ans;
inline void initial() {
s[0] = '~'; // 好初始化
s[cnt = 1] = '|';
while (!isalpha(c = getchar())) ;
while (isalpha(c)) {
s[++cnt] = c;
s[++cnt] = '|';
c = getchar();
}
}
int main() {
initial();
for (int i = 1; i <= cnt; i++) {
p[i] = mx > i ? min(p[2*id-i], mx-i) : 1;
while (s[i-p[i]] == s[i+p[i]]) p[i] ++;
if (i + p[i] > mx) {
mx = p[i] + i;
id = i;
}
ans = max(ans, p[i]);
}
printf("%d\n", ans-1);
return 0;
}