求最長迴文子串。
字面意思
這麼求??
暴力:
枚舉某個點爲迴文中心,向兩邊擴展。(在每個字符中間再插一個沒出現過的字符以保證迴文子串長度爲偶數的情況)
時間複雜度:
然而可以線性時間:
根據迴文串的性質:左右對稱
我們可以得出在某一個迴文串中,以它迴文中心右邊的某個點爲迴文中心的最長迴文子串長度不小於以它左邊對稱點爲中心的最長迴文子串的長度
於是:
當
有
在這基礎上再向左右擴展
當然,還有一些特殊情況:出界,右邊的迴文串長一些(cccbcc中b爲中心,最右邊)等。。。
F[i]=max( 0,min( F[2*p-i],p+F[p]-i ) );
理解一下這條語句
在此基礎上再向左右擴展下去
while(s[i-F[i]]==s[i+F[i]]) F[i]++;
當以新的
裸題:HDU3068
貼代碼:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<math.h>
#include<string.h>
//#include<>
using namespace std;
char str[120000],s[240000];
int ans,F[240000];
void pre()
{
s[0]='@';
int l=strlen(str);
for(int i=0;i<l;i++)
{
s[i*2+1]='#';
s[i*2+2]=str[i];
}
s[(l-1)*2+3]='#';
s[(l-1)*2+4]='%';
}
void manacher()
{
int n=(strlen(str)-1)*2+4;
F[0]=F[1]=ans=0;
int p=1;
for(int i=2;i<=n;i++)
{
F[i]=max( 0,min( F[2*p-i],p+F[p]-i ) );
while(s[i-F[i]]==s[i+F[i]]) F[i]++;
if(i+F[i]>p+F[p]) p=i;
ans=max(ans,F[i]);
}
}
int main()
{
while(scanf("%s",&str)!=EOF)
{
pre();
manacher();
printf("%d\n",ans-1);
}
return 0;
}