回文自动机(BZOJ2565)

时间:2023-03-09 14:47:45
回文自动机(BZOJ2565)
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; int p,next[][],cnt[],len[],fail[],last,a[],maxl[],maxr[];
char st[]; int newnode(int l){
p++;
for (int i=;i<=;i++) next[p][i]=;
cnt[p]=;
len[p]=l;
return(p);
} void init(){
p=-;
newnode();
newnode(-);
last=;
st[]=-;
fail[]=;
} int get_fail(int po,int x,int num){
while (a[po-len[x]-]!=num) x=fail[x];
return(x);
} void add(int po,int c){
int cur=get_fail(po,last,c);
if (!next[cur][c]){
int now=newnode(len[cur]+);
fail[now]=next[get_fail(po,fail[cur],c)][c];
next[cur][c]=now;
}
last=next[cur][c];
cnt[last]++;
} void count(){
for (int i=p;i>=;i--) cnt[fail[i]]+=cnt[i];
} int main(){
scanf("%s",&st);
int n=strlen(st);
for (int i=;i<=n;i++) a[i]=st[i-]-'a'+; init();
for (int i=;i<=n;i++)
add(i,a[i]),maxl[i]=len[last];
count(); for (int i=;i<=n/;i++){
int t=a[i];a[i]=a[n-i+];a[n-i+]=t;
}
init();
for (int i=;i<=n;i++)
add(i,a[i]),maxr[n-i+]=len[last];
count(); int ans=;
for (int i=;i<n;i++) ans=max(ans,maxl[i]+maxr[i+]);
printf("%d\n",ans);
}

每个节点表示一个本质不同的回文串(最多n个)。

进行count()后,cnt中存每个本质不同的回文串的出现次数。

------------------------------------------------------------------------

CODECHEF APRIL LUNCHTIME 2015 PALPROB

在fail树上转移palindromness

#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#define LL long long
using namespace std; map <int,int> mp,mpb;
int p,tr[][],cnt[],len[],fail[],last,a[],maxl[],maxr[];
int ans[],nd[],nxt[],des[],T,scnt;
char st[]; void addedge(int x,int y){
nxt[++scnt]=nd[x];des[scnt]=y;nd[x]=scnt;
} int newnode(int l){
p++;
for (int i=;i<=;i++) tr[p][i]=;
cnt[p]=;ans[p]=;
len[p]=l;
return(p);
} void init(){
p=-;
newnode();newnode(-);
last=;
st[]=-;
fail[]=;
} int get_fail(int po,int x,int num){
while (a[po-len[x]-]!=num) x=fail[x];
return(x);
} void add(int po,int c){
int cur=get_fail(po,last,c);
if (tr[cur][c]==){
int now=newnode(len[cur]+);
fail[now]=tr[get_fail(po,fail[cur],c)][c];
tr[cur][c]=now;
}
last=tr[cur][c];
cnt[last]++;
} void count(){
for (int i=p;i>=;i--) cnt[fail[i]]+=cnt[i];
} void dfs(int po){
if (len[po]>=){
int t;
if (len[po]<=) t=-;else t=len[po]/;
int p=mp[t];
if (mpb[t])
ans[po]=ans[p]+;else
ans[po]=;
} mpb[len[po]]=;mp[len[po]]=po;
for (int p=nd[po];p!=-;p=nxt[p])
dfs(des[p]);
mpb[len[po]]=;
} int main(){
freopen("a.in","r",stdin); scanf("%d",&T);
while (T--){
scanf("%s",&st);
int n=strlen(st);
for (int i=;i<=n;i++) a[i]=st[i-]-'a'+; init();
for (int i=;i<=n;i++)
add(i,a[i]);
count(); for (int i=;i<=p;i++) nd[i]=-;scnt=;
for (int i=;i<=p;i++) if (i!=) addedge(fail[i],i); mp.clear();mpb.clear();
dfs(); LL ret=;
for (int i=;i<=p;i++) ret+=(LL)ans[i]*cnt[i];
printf("%lld\n",ret);
}
}