跑两遍PAM.分别找到每个点做为结尾字符和开始字符的最长回文串的长度.
/* I will wait for you */ #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; const int maxn=500010; const int maxm=1010; const int maxs=26; const int INF=1<<29; const int P=1000000007; const double error=1e-9; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') f=(ch=='-'?-1:1),ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } struct pam { pam *fa,*next[maxs];int len,val; }su[maxn],*headf,*heads,*last; int n,pos,cnt,ans,l[maxn],r[maxn];char s[maxn]; void init() { s[0]='~',pos=0; headf=&su[++cnt],last=heads=&su[++cnt]; headf->fa=heads,heads->len=-1; } void add(int x) { pam *per=last; for(pos++;s[pos-per->len-1]!=s[pos];per=per->fa); if(!per->next[x]) { pam *now=&su[++cnt]; last=per->next[x]=now,now->len=per->len+2; if(per==heads) now->fa=headf; else { for(per=per->fa;s[pos-per->len-1]!=s[pos];per=per->fa); now->fa=per->next[x]; } } else last=per->next[x]; } int main() { scanf("%s",s+1),n=strlen(s+1); init(); for(int i=1;i<=n;i++) add(s[i]-'a'),l[i]=last->len; init(); for(int i=1;i<=n/2;i++) swap(s[i],s[n-i+1]); for(int i=1;i<=n;i++) add(s[i]-'a'),r[n-i+1]=last->len; for(int i=1;i<n;i++) ans=max(ans,l[i]+r[i+1]); printf("%d\n",ans); return 0; }膜拜一下lowsfish的BZOJ rank 1的做法.
每次求出以当前字符String[now]做结尾字符的最长回文串的长度lenth[now].用lenth[now]+lenth[now-lenth[now]]更新答案.
/* I will wait for you */ #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; const int maxn=100010; const int maxm=1010; const int maxs=26; const int INF=1<<29; const int P=1000000007; const double error=1e-9; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') f=(ch=='-'?-1:1),ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } struct pam { pam *fa,*next[maxs];int len; }su[maxn],*headf,*heads,*last; int n,pos,cnt,ans,f[maxn];char s[maxn]; void init() { s[0]='~',pos=0; headf=&su[++cnt],last=heads=&su[++cnt]; headf->fa=heads,heads->len=-1; } inline void add(int x) { pam *per=last; for(pos++;s[pos-per->len-1]!=s[pos];per=per->fa); if(!per->next[x]) { pam *now=&su[++cnt]; last=per->next[x]=now,now->len=per->len+2; if(per==heads) now->fa=headf; else { for(per=per->fa;s[pos-per->len-1]!=s[pos];per=per->fa); now->fa=per->next[x]; } } else last=per->next[x]; } int main() { scanf("%s",s+1),n=strlen(s+1),init(); for(int i=1;i<=n;i++) add(s[i]-'a'),ans=max(ans,(f[i]=last->len)+f[i-f[i]]); printf("%d\n",ans); return 0; }