Sample Input
6 1 a 1 b 2 a 2 c 3 4 8 1 a 2 a 2 a 1 a 3 1 b 3 4
Sample Output
4 5 4 5 11
题意:多组输入,开始字符串为空,支持4中操作: 1,在字符串首加字符; 2,在字符串尾加字符; 3,查询字符串不同本质的回文串个数; 4,查询回文串个数总和
思路:因为支持首尾加入,所以和常规的回文树有些不同。 参考了YYB的博客。 发现首尾互相影响,当且仅当整个字符串是回文串。 其他情况两头正常加即可。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) #define rep2(i,a,b) for(int i=a;i>=b;i--) using namespace std; const int maxn=100010; struct PAT { struct node{ int len,num,fail,son[26]; }t[maxn]; int n,tot,s[maxn<<1],L,R,suf,pre; ll ans; void init() { memset(t,0,sizeof(t)); memset(s,-1,sizeof(s)); tot=1; L=100000; R=L-1; suf=pre=0; ans=0; t[1].len=-1; t[0].fail=t[1].fail=1; } void add(int c,int n,int &last,int op){ int p=last; s[n]=c; while(s[n]!=s[n-op-op*t[p].len]) p=t[p].fail; if(!t[p].son[c]){ int v=++tot,k=t[p].fail; while(s[n]!=s[n-op*t[k].len-op]) k=t[k].fail; t[v].fail=t[k].son[c]; t[v].len=t[p].len+2; t[v].num=t[t[v].fail].num+1; t[p].son[c]=v; } last=t[p].son[c]; ans+=t[last].num; if(t[last].len==R-L+1) suf=pre=last; } }T; int main() { int N; while(~scanf("%d",&N)){ T.init(); int opt; rep(i,1,N){ scanf("%d",&opt); char s[3]; if(opt==1){ scanf("%s",s); T.add(s[0]-‘a‘,--T.L,T.pre,-1); } else if(opt==2){ scanf("%s",s); T.add(s[0]-‘a‘,++T.R,T.suf,1); } else if(opt==3) printf("%d\n",T.tot-1); else printf("%lld\n",T.ans); } } return 0; }
原文地址:https://www.cnblogs.com/hua-dong/p/10355974.html
时间: 2024-10-03 09:04:01