裸的SAM暴力程序跑得很快.
/* I will wait for you */ #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<iostream> #include<fstream> #include<vector> #include<queue> #include<deque> #include<set> #include<map> #include<string> #define make make_pair #define fi first #define se second using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; const int maxn=2000010; const int maxm=1010; const int maxs=26; const int INF=1<<29; const int P=1000000007; const double error=1e-9; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') f=(ch=='-'?-1:1),ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } struct sam { sam *fa,*next[maxs]; int len,val; }su[maxn],*head,*tail; char s[maxn],t[10]; int mas,cnt; void init() { head=tail=&su[cnt++]; } void add(int x) { sam *now=&su[cnt++],*per=tail; now->len=per->len+1,tail=now; for(;per&&!per->next[x];per->next[x]=now,per=per->fa); if(!per) now->fa=head; else if(per->len+1==per->next[x]->len) now->fa=per->next[x]; else { sam *tmp=&su[cnt++],*pex=per->next[x]; *tmp=*pex;tmp->len=per->len+1; pex->fa=now->fa=tmp; for(;per&&per->next[x]==pex;per->next[x]=tmp,per=per->fa); } for(;now!=head;now=now->fa) now->val++; } void insert(char* s) { for(int i=0,n=strlen(s);i<n;i++) add(s[i]-'A'); } int query(char* s) { sam *now=head; for(int i=0,n=strlen(s);i<n&&(now=now->next[s[i]-'A']);i++); return now?now->val:0; } void mask(char* s,int m) { for(int i=0,n=strlen(s);i<n;i++) m=(m*131+i)%n,swap(s[i],s[m]); } int main() { int n=read();init(); scanf("%s",s),insert(s); for(int i=1,q;i<=n;i++) { scanf("%s%s",t,s),mask(s,mas); if(t[0]=='A') insert(s); if(t[0]=='Q') q=query(s),mas^=q,printf("%d\n",q); } return 0; }注意到fail指针构成了一颗树.而每次插入新节点对整体的影响是一条到根节点的链.因此可以用LCT维护.
/* I will wait for you */ #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<iostream> #include<fstream> #include<vector> #include<queue> #include<deque> #include<set> #include<map> #include<string> #define make make_pair #define fi first #define se second using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; const int maxn=2000010; const int maxm=1010; const int maxs=26; const int INF=1<<29; const int P=1000000007; const double error=1e-9; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') f=(ch=='-'?-1:1),ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } char s[maxn],t[10];int mas,cntn,cnts; struct node { int val,add;node *fa,*son[2]; int dir() { return this==fa->son[1]; } int isroot() { return !fa||this!=fa->son[0]&&this!=fa->son[1]; } }no[maxn]; node* newc(int c) { node* o=&no[cntn++]; o->val=c,o->add=0,o->fa=o->son[0]=o->son[1]=0; return o; } void pushdown(node *o) { if(o->add) { for(int i=0;i<2;i++) if(o->son[i]) o->son[i]->add+=o->add,o->son[i]->val+=o->add; o->add=0; } } void maintain(node *o) { for(int i=0;i<2;i++) if(o->son[i]) o->son[i]->fa=o; } void rotate(node *o) { node* p=o->fa;int d=o->dir(); pushdown(p);pushdown(o); p->son[d]=o->son[d^1]; o->son[d^1]=p,o->fa=p->fa; if(!p->isroot()) p->fa->son[p->dir()]=o; maintain(p),maintain(o); } void splay(node *o) { pushdown(o); while(!o->isroot()) { node *p=o->fa; if(p->isroot()) rotate(o); else if(o->dir()==p->dir()) rotate(p),rotate(o); else rotate(o),rotate(o); } } void access(node* o) { for(node* t=0;o;t=o,o=o->fa) splay(o),o->son[1]=t,maintain(o); } void link(node* u,node* v) { u->fa=v; } void cut(node* u) { access(u),splay(u); if(u->son[0]) { u=u->son[0]; while(u->son[1]) u=u->son[1]; splay(u),u->son[1]=0; } } struct sam { sam *fa,*next[maxs];int len;node* c; }su[maxn],*head,*tail; void init() { head=&su[cnts++],head->c=newc(0),tail=head; } void add(int x) { sam *now=&su[cnts++],*per=tail; now->len=per->len+1,now->c=newc(0),tail=now; for(;per&&!per->next[x];per->next[x]=now,per=per->fa); if(!per) now->fa=head,link(now->c,head->c); else if(per->len+1==per->next[x]->len) now->fa=per->next[x],link(now->c,per->next[x]->c); else { sam *tmp=&su[cnts++],*pex=per->next[x]; cut(pex->c),*tmp=*pex; tmp->len=per->len+1,tmp->c=newc(pex->c->val); link(tmp->c,tmp->fa->c); pex->fa=now->fa=tmp; link(pex->c,tmp->c),link(now->c,tmp->c); for(;per&&per->next[x]==pex;per->next[x]=tmp,per=per->fa); } access(now->c),splay(now->c),now->c->add++,now->c->val++; } void insert(char* s) { for(int i=0,n=strlen(s);i<n;i++) add(s[i]-'A'); } int query(char* s) { sam *now=head; for(int i=0,n=strlen(s);i<n&&(now=now->next[s[i]-'A']);i++); return now?(splay(now->c),now->c->val):0; } void mask(char* s,int m) { for(int i=0,n=strlen(s);i<n;i++) m=(m*131+i)%n,swap(s[i],s[m]); } int main() { int n=read();init(); scanf("%s",s),insert(s); for(int i=1,q;i<=n;i++) { scanf("%s%s",t,s),mask(s,mas); if(t[0]=='A') insert(s); if(t[0]=='Q') q=query(s),mas^=q,printf("%d\n",q); } return 0; }