BZOJ2555: SubString
这题写得我真想吐...
主要注意一个地方。
1.每次cut的时候,cut的一颗子树,而不是只有q这个节点。
说到底,还是没有对fail树的形态有一个清晰地认识,不过这道题写后就好很多。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define mem1(i,j) memset(i,j,sizeof(i))
#define mem2(i,j) memcpy(i,j,sizeof(i))
#define LL long long
#define up(i,j,n) for(int i=(j);i<=(n);i++)
#define FILE "dealing"
#define poi vec
#define eps 1e-10
#define db double
const int maxn=1620000,inf=1000000000,mod=1000000007;
int read(){
int x=0,f=1,ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0',ch=getchar();}
return f*x;
}
bool cmax(int& a,int b){return a<b?a=b,true:false;}
bool cmin(int& a,int b){return a>b?a=b,true:false;}
string s;char ch[maxn];int mask=0;
namespace LCT{
int c[maxn][2],fa[maxn],val[maxn],siz[maxn],rev[maxn],delet[maxn];
bool isroot(int x){if(!x)return 1;return c[fa[x]][1]!=x&&c[fa[x]][0]!=x;}
//void revv(int x){if(!x)return;swap(c[x][0],c[x][1]);rev[x]^=1;}
void add(int x,int d){if(!x)return;delet[x]+=d;val[x]+=d;}
void pushdown(int x){
if(!x)return;
//if(rev[x]){rev[x]^=1;revv(c[x][1]);revv(c[x][0]);}
if(delet[x])add(c[x][1],delet[x]),add(c[x][0],delet[x]),delet[x]=0;
}
void rotate(int x){
if(!x)return;
int y=fa[x],z=fa[y],d=c[y][1]==x;
if(!isroot(y))c[z][c[z][1]==y]=x;
fa[y]=x;fa[x]=z;if(c[x][d^1])fa[c[x][d^1]]=y;
c[y][d]=c[x][d^1];c[x][d^1]=y;
}
int q[maxn],top=0;
void splay(int x){
q[++top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
while(top)pushdown(q[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][1]==x^c[z][1]==y)rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x){for(int t=0;x;t=x,x=fa[x])splay(x),c[x][1]=t;}
void cut(int x){
access(x);splay(x);
add(c[x][0],-val[x]);
c[x][0]=fa[c[x][0]]=0;
}
void link(int x,int y){
access(y);splay(y);fa[x]=y;
add(y,val[x]);
}
};
namespace SAM{
int c[maxn][26],pre[maxn],len[maxn],cnt=1,now=1,Now=1;
void extend(int x){
int nq,np,q,p;
p=Now;Now=np=++cnt;len[np]=len[p]+1;LCT::val[np]++;
while(p&&!c[p][x])c[p][x]=np,p=pre[p];
if(!p){pre[np]=1;
LCT::link(np,1);
}
else {
q=c[p][x];
if(len[q]==len[p]+1)pre[np]=q,LCT::link(np,q);
else {
len[nq=++cnt]=len[p]+1;
mem2(c[nq],c[q]);
pre[nq]=pre[q];
LCT::link(nq,pre[q]);
LCT::cut(q);
LCT::link(q,nq);
LCT::link(np,nq);
pre[q]=pre[np]=nq;
while(p&&c[p][x]==q)c[p][x]=nq,p=pre[p];
}
}
}
int Len=0;
void prepare(){Len=0,now=1;}
int walk(int x){
while(pre[now]&&!c[now][x])now=pre[now],Len=len[now];
if(!c[now][x])return 0;
now=c[now][x];Len++;return Len;
}
int solve(){
LCT::access(now);LCT::splay(now);return LCT::val[now];
}
void build(char* s){
int n=strlen(s+1);Now=1,cnt=1;
up(i,1,n)extend(s[i]-'A');
}
};
void load(int mask){
scanf("%s",ch);
s=ch;
up(j,0,s.length()-1){
mask=(mask*131+j)%s.length();
char t=s[j];
s[j]=s[mask];
s[mask]=t;
}
}
int main(){
//freopen(FILE".in","r",stdin);
//freopen(FILE".out","w",stdout);
int Q=read();
scanf("%s",ch+1);
SAM::build(ch);
while(Q--){
scanf("%s",ch+1);
if(ch[1]=='Q'){
load(mask);
//cin>>s;
SAM::prepare();int n=s.length(),m;
up(i,0,n-1)m=SAM::walk(s[i]-'A');
int ans=(m==n?SAM::solve():0);
mask^=ans;
printf("%d\n",ans);
}
else {
load(mask);
//cin>>s;
int n=s.length();
up(i,0,n-1)SAM::extend(s[i]-'A');
}
}
return 0;
}

浙公网安备 33010602011771号