裸的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;
}