#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);//差值爲需要加多少達到迴文串,加長度爲加之後的迴文串長度
}
}
Manacher算法--O(n)迴文子串算法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.