Manacher算法--O(n)迴文子串算法

馬拉車算法詳解地址

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int p[2000010];//記錄以s[i]爲中心的迴文串最大可向右延伸幾位,p[i]-1爲原串以i爲中心的最長迴文串長度
int Find(string s)
{
    int mx=0,id=0;//mx記錄向右延伸到的最大值,id記錄最長迴文串的中心下標
    memset(p,0,sizeof(p));
    int l=s.size();
    for(int i=1; i<l; i++)
    {
        if(mx>i)
            p[i]=min(p[2*id-i],mx-i);//j=2*id-i ;   id爲i與j的對稱點,當mx-i>p[j],i會延伸到和j一樣,反之會延伸到和mx-i一樣
        else
            p[i]=1;
        while(s[i-p[i]]==s[i+p[i]])//一個一個往後匹配相同長度加1
            p[i]++;
        if(i+p[i]>mx)//更新mx和id
        {
            mx=i+p[i];
            id=i;
        }
    }
    for(int i=0; i<l; i++)
        if(i+p[i]==l)//找到可延伸到原串最後的最長迴文串,返回長度
            return p[i]-1;
}
int main()
{
    int ncase,Z=0;
    scanf("%d",&ncase);
    while(ncase--)
    {
        string str,x;
        x+='$';//防止while判斷越界
        x+='#';
        cin>>str;
        int l=str.size();
        for(int i=0; i<l; i++)//解決奇偶迴文串,全變爲奇數
        {
            x+=str[i];
            x+='#';
        }
        //如果用char記得在最後加反斜槓0
        printf("Case %d: %d\n",++Z,l-Find(x)+l);//差值爲需要加多少達到迴文串,加長度爲加之後的迴文串長度
    }
}
發佈了110 篇原創文章 · 獲贊 18 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章