馬拉車(manacher)

馬拉車

簡介

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就是答案啦

當下標 s[i]==s[j](i<j)s[i] == s[j](i<j)idid 爲中心對稱時, p[j]p[j] 可以由 p[i]p[i] 推出, p[i]p[i] 同樣可以由 p[j]p[j] 推出
mx>imx>i ,即當前下標處於迴文串中,與下標 ii 對稱的 jj 滿足 i+j=2×idi+j=2 \times id 。但是!!!要注意 p[i]+ip[i]+i 一定是小於等於 mxmx ,即 p[i]mxip[i] \leq mx-i,兩者取下最小值就可以得到 p[i]p[i]

應用

題目
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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章