HDU-5421 Victor and String
题意
给定一个空串(S),有(n)次操作,操作有如下四种:
- (1~c),在(S)前增加一个字符(c)。
- (2~c),在(S)后增加一个字符(c)。
- (3),输出(S)中本质不同的回文子串个数。
- (4),输出(S)中不同的回文子串个数,位置不同的子串算多个。
(nle 10^5)
分析
回文自动机额外记录一个前端插入的last即可,前端插入和后端插入操作是类似的,唯一和之前不同的地方是当(last)是整个串时,要更新另外一端的(last)为当前这一端的(last)。
Code
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
#define ll long long
using namespace std;
const int inf=1e9;
const int mod=1e9+7;
const int maxn=5e5+10;
char s[maxn];
int n,now,l,r;
ll ans;
struct PAM{
int son[maxn][26],fail[maxn],len[maxn],cnt[maxn],tot,suf,pre,last;
int newnode(int x){
++tot;
for(int i=0;i<26;i++) son[tot][i]=0;
fail[tot]=0;len[tot]=x;
return tot;
}
void init(){
tot=-1;newnode(0);newnode(-1);
fail[0]=1;
suf=pre=0;
l=1e5+5,r=l-1;
}
int gao(int x,int op){
while(s[now+op*len[x]+op]!=s[now]) x=fail[x];
return x;
}
void insert(int op){
int last=op==1?pre:suf;
int p=gao(last,op);
if(!son[p][s[now]-'a']){
int tmp=son[gao(fail[p],op)][s[now]-'a'];
son[p][s[now]-'a']=newnode(len[p]+2);
fail[tot]=tmp;
cnt[tot]=cnt[tmp]+1;
}
last=son[p][s[now]-'a'];
ans+=cnt[last];
if(op==1) pre=last;
else suf=last;
if(len[last]==r-l+1) suf=pre=last;
}
int qy(){
return len[last];
}
}P;
int main(){
while(~scanf("%d",&n)){
memset(s,0,sizeof(s));
P.init();
ans=0;
while(n--){
int op;
char c;
scanf("%d",&op);
if(op==1){
scanf(" %c",&c);
s[--l]=c;
now=l;
P.insert(1);
}else if(op==2){
scanf(" %c",&c);
s[++r]=c;
now=r;
P.insert(-1);
}else if(op==3){
printf("%d
",P.tot-1);
}else{
printf("%lld
",ans);
}
}
}
return 0;
}