题意
动态在串的前后插入字符,问当前本质不同的回文串个数,和所有回文串个数
题解
如果只有后端插入,那么就是回文自动机的模板
考虑前端插入的影响
我们在后端插入时,一直维护着最长回文后缀,那么在前端插入的时候,很自然想到维护最长回文前缀,事实上确实是这样做的
跟后端插入一样,我们考虑维护一个 fail' f a i l ′ 表示一个串的最长回文前缀.那么每次前端插入就沿着 fail' f a i l ′ 跑就好了
然而事实上,对于一个点 t t 而言,由于是回文串, t t 的每一个回文后缀的翻转,都和 t t 的回文前缀相等,而 t′ t ′ 和 t′′ t ″ 本身又是回文串,那么 t′=t′′ t ′ = t ″ 所以 fail′ f a i l ′ 实际上就是 fail f a i l
那么,我们只用考虑维护当前最长回文前缀和后缀就好了
注意在前(后)端插入时,不仅会改变对最长回文前(后)缀,还有可能对最长回文后(前)缀造成影响,而这个情况很明显,就是整个串是回文串的时候
#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
template<class T>inline void we(T x){
if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=2e5+5;
typedef int arr[N];
typedef long long ll;
int m;char s[N];
struct node{
int ch[26],fail,len;
inline void New(int a,int b){
memset(ch,0,sizeof ch);fail=a,len=b;
}
};
struct PAM{
int L,R,tot,las[2];arr s,dep;node a[N];ll sum;
inline void init(int n){
L=n,R=n-1,memset(s,-1,sizeof s),tot=1;
sum=las[0]=las[1]=0;a[0].New(1,0),a[1].New(0,-1);
}
inline int gf(int x,int d){
if(d)while(s[R-a[x].len-1]^s[R])x=a[x].fail;
else while(s[L+a[x].len+1]^s[L])x=a[x].fail;
return x;
}
inline void ins(int v,int d){
d?s[++R]=v:s[--L]=v;
int&u=tot;las[d]=gf(las[d],d);
if(!a[las[d]].ch[v]){
a[++u].New(a[gf(a[las[d]].fail,d)].ch[v],a[las[d]].len+2);
a[las[d]].ch[v]=u,dep[u]=dep[a[u].fail]+1;
}las[d]=a[las[d]].ch[v];sum+=dep[las[d]];
if(a[las[d]].len==R-L+1)las[d^1]=las[d];//最后一句所说的特判
}
}p;
inline void sol(){
int op;char c;p.init(m);
while(m--){
scanf("%d",&op);
switch(op){
case 1:case 2:
scanf(" %c",&c);p.ins(c-'a',op-1);
break;
case 3:we(p.tot-1);break;
case 4:we(p.sum);break;
}
}
}
int main(){
#ifndef ONLINE_JUDGE
file("s");
#endif
while(~scanf("%d",&m))sol();
return Ot(),0;
}