HDU - 3068 最長迴文(馬拉車Manacher)題解

思路:馬拉車裸題,我們用一個p[i]數組代表以i爲中心的最大回文半徑。這裏用了一個小技巧,如果一個串是aaaa這樣的,那我們插入不相干的字符使它成爲#a#a#a#a#,這樣無論這個串是奇數還是偶數都會變成奇數,容易處理。馬拉車的效率在於,在暴力處理前面的迴文時,我們可以初始化後面的p[j],減少暴力的時間,這樣複雜度就從O(n^2)變成了O(n)。這裏要注意一下,我們得到的p[i]所指向的不一定是數字,也有可能是‘#’,比如$#a#b#b#a#中最大的是p[5]。

可以看看這個博客,很容易理解

代碼:

#include<set>
#include<iostream>
#include<algorithm>
const int maxn = 110000+5;
const int INF = 0x3f3f3f3f;
using namespace std;
int p[maxn<<1];
char snew[maxn<<1],s[maxn];
int init(){
    int len = strlen(s),cnt = 0;
    snew[0] = '$';
    for(int i = 0;i < len;i++){
        snew[++cnt] = '#';
        snew[++cnt] = s[i];
    }
    snew[++cnt] = '#';
    snew[++cnt] = '\0';
    return cnt;
}
int Manacher(){
    int cnt = init();
    int id = 0,ans = -1;
    for(int i = 2;i < cnt;i++){
        if(p[id] + id > i){
            p[i] = min(p[2*id - i],p[id] + id - i);
        }
        else p[i] = 1;
        while(snew[i - p[i]] == snew[i + p[i]])
            p[i]++;
        if(id + p[id] < i + p[i])
            id = i;
        ans = max(ans,p[i] - 1);
    }
    return ans;
}
int main(){
    while(scanf("%s",s) != EOF){
        printf("%d\n",Manacher());
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章