题目:http://acm.hdu.edu.cn/showproblem.php?pid=5421
因为要在前面插字符,所以维护一个前缀链和后缀链,在同一棵回文树上搞,如果有某个最长回文后缀(或前缀)的长度为总长,那让前缀(或后缀)的last也赋为当前结点。
#include<cstring> #include<iostream> #include<algorithm> #include<cstdio> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define ll long long #define maxn 200500 using namespace std; int n,op; char c; int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f; } struct data{ ll sum; int L,R,tot,fail[maxn],l[maxn],nxt[maxn][30],s[maxn],last[2],cnt[maxn]; int newnode(int len){ clr(nxt[tot],0); l[tot]=len; cnt[tot]=0; return tot++; } void init(){ tot=0; sum=0; newnode(0); newnode(-1); fail[0]=1; last[0]=last[1]=1; clr(s,-1); L=n; R=n-1; } int getfail(int op,int v){ if (op) while (s[R-l[v]-1]!=s[R]) v=fail[v]; else while (s[L+l[v]+1]!=s[L]) v=fail[v]; return v; } void add(int op,int c){ if (op) s[++R]=c; else s[--L]=c; int cur=getfail(op,last[op]); if (!nxt[cur][c]){ int now=newnode(l[cur]+2); fail[now]=nxt[getfail(op,fail[cur])][c]; nxt[cur][c]=now; cnt[now]=cnt[fail[now]]+1; } last[op]=nxt[cur][c]; if (l[last[op]]==R-L+1) last[op^1]=last[op]; sum+=cnt[last[op]]; } }T; int main(){ // freopen("in.txt","r",stdin); while (~scanf("%d",&n)){ T.init(); rep(i,1,n){ op=read(); if (op<=2) { c=getchar(); T.add(op-1,c-'a'); } else if(op==3) printf("%d ",T.tot-2); else printf("%lld ",T.sum); } } return 0; }