不懂SAM的可以一起讨论加深理解,因为我也不太懂
hdu4622,CLJ大爷出的模板题
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(a,b,c) for (int a=b;a<=c;a++)
const int N=4010;
using namespace std;
int ans;
struct suffix_automaton{
int f[N],s[N][26],mx[N],last,tot;
void clear(){memset(s[last=tot=0],0,104);}
int newnode(int k){
mx[++tot]=k;
f[tot]=0;
memset(s[tot],0,104);
return tot;
}
void extend(int c){
int p=last,np=last=newnode(p[mx]+1);
for (;~p&&!p[s][c];p=p[f]) p[s][c]=np;
ans+=np[mx];
if (p<0) return;
int q=p[s][c];
if (q[mx]==p[mx]+1){
ans-=q[mx];
np[f]=q;
return;
}
int nq=newnode(p[mx]+1);
nq[f]=q[f];
q[f]=np[f]=nq;
ans-=nq[mx];
memcpy(nq[s],q[s],104);
for (;~p&&p[s][c]==q;p=p[f]) p[s][c]=nq;
}
}sam;
int f[2010][2010];
void work(){
static char s[N];
scanf("%s",s);
int n=strlen(s);
rep(i,0,n-1){
ans=0;
sam.clear();
rep(j,i,n-1){
sam.extend(s[j]-'a');
f[i][j]=ans;
}
}
int q;
scanf("%d",&q);
while (q--){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",f[x-1][y-1]);
}
}
int main(){
sam.f[0]=-1;
int t;
scanf("%d",&t);
while (t--) work();
return 0;
}
BZOJ3926,CLJ大爷出的trie上SAM模板题
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(a,b,c) for (int a=b;a<=c;a++)
#define mp make_pair
#define x first
#define y second
const int N=100010,ND=4000010;
using namespace std;
typedef long long LL;
typedef pair <int,int> par;
par q[ND];
int h,t,n,c[N],d[N],ft[N],fa[ND],tot;
struct edge{int t,n;}E[N<<1];
void link(int u,int v){
++d[u],++d[v];
E[++tot]=(edge){v,ft[u]},ft[u]=tot;
E[++tot]=(edge){u,ft[v]},ft[v]=tot;
}
struct SAM{
int tot,f[ND],s[ND][10],mx[ND];
void init(){
f[0]=-1;
}
int newnode(int k){
mx[++tot]=k;
return tot;
}
int extend(int cur,int c){
int p=cur;
if (p[s][c]) return p[s][c];
int np=newnode(p[mx]+1);
for (;~p&&!p[s][c];p=p[f]) p[s][c]=np;
if (p<0) return np;
int q=p[s][c];
if (q[mx]!=p[mx]+1){
int nq=newnode(p[mx]+1);
nq[f]=q[f];
q[f]=np[f]=nq;
memcpy(nq[s],q[s],40);
for (;~p&&p[s][c]==q;p=p[f]) p[s][c]=nq;
} else np[f]=q;
return np;
}
LL ask(){
LL ans=0;
rep(i,1,tot) ans+=i[mx]-i[f][mx];
return ans;
}
}sam;
int main(){
sam.init();
scanf("%d%d",&n,c);
rep(i,1,n) scanf("%d",c+i);
rep(i,1,n-1){
int u,v;
scanf("%d%d",&u,&v);
link(u,v);
}
rep(i,1,n) if (d[i]==1) q[++t]=mp(i,0);
rep(i,1,t) q[i].y=sam.extend(0,c[q[i].x]);
for (;h<t;){
par k=q[++h];
int u=k.x,p=k.y;
for (int o=ft[u],v;v=E[o].t;o=E[o].n) if (v!=fa[h])
q[++t]=mp(v,sam.extend(p,c[v])),fa[t]=u;
}
printf("%lld\n",sam.ask());
return 0;
}
BZOJ2555,CLJ大爷出的LCT维护SAM的parent tree模板题
调了90min无果,重构一下代码30min就过了
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define rep(a,b,c) for (int a=b;a<=c;a++)
using namespace std;
const int N=1200010;
char S[3000010];
struct dat{
dat *f,*s[2];
int k,t;
void operator +=(int x){
k+=x,t+=x;
}
void down(){
(*s[0])+=t;
(*s[1])+=t;
t=0;
}
}a0[N]={{a0,{a0,a0}}};
#define isroot(x) (x->f==a0||(x->f->s[0]!=x&&x->f->s[1]!=x))
void rot(dat *x){
dat *y=x->f,*z=y->f;
bool dx=x==y->s[1],dy=y==z->s[1];
x->f=z;
if (!isroot(y)) z->s[dy]=x;
(y->s[dx]=x->s[!dx])->f=y;
(x->s[!dx]=y)->f=x;
}
void splay(dat *x){
static dat *q[N];
int t=0;
do q[++t]=x,x=x->f; while (!isroot(q[t]));
while (t) q[t--]->down();
for (x=q[1];!isroot(x);rot(x)){
dat *y=x->f,*z=y->f;
if (isroot(y)) continue;
bool dx=x==y->s[1],dy=y==z->s[1];
if (dx==dy) rot(y); else rot(x);
}
}
void access(dat *x){
dat *a=a0,*b=x;
for (;b!=a0;a=b,b=b->f)
splay(b),b->s[1]=a;
splay(x);
}
void cut(dat *x){
access(x);
x->s[0]->f=a0;
(*x->s[0])+=-x->k;
x->s[0]=a0;
}
void link(dat *x,dat *y){
access(y);
(*y)+=x->k;
x->f=y;
}
void node(int x,int k){
a0[x]=(dat){a0,{a0,a0},k,0};
}
struct SAM{
int tot,cur,f[N],s[N][26],mx[N];
void init(){
cur=tot=1;
node(1,0);
}
int newnode(int k){
mx[++tot]=k;
return tot;
}
void extend(int c){
static int p,np,q,nq;
p=cur;
cur=np=newnode(mx[p]+1);
node(np,1);
for (;p&&!p[s][c];p=p[f]) p[s][c]=np;
if (!p) {
link(a0+np,a0+1);
np[f]=1;
return;
}
q=p[s][c];
if (q[mx]!=p[mx]+1){
nq=newnode(p[mx]+1);
node(nq,0);
memcpy(nq[s],q[s],104);
for (;p&&p[s][c]==q;p=p[f]) p[s][c]=nq;
cut(a0+q);
link(a0+q,a0+nq);
link(a0+np,a0+nq);
link(a0+nq,a0+q[f]);
nq[f]=q[f];
q[f]=np[f]=nq;
} else {
link(a0+np,a0+q);
np[f]=q;
}
}
int ask(){
int n=strlen(S),c=1;
rep(i,0,n-1) if (!c[s][S[i]-'A']) return 0;
else c=c[s][S[i]-'A'];
splay(a0+c);
return (a0+c)->k;
}
}sam;
string chars;
void gets(int mask){
scanf("%s",S);
chars=S;
for (int j=0;j<chars.length();j++)
{
mask=(mask*131+j)%chars.length();
char t=chars[j];
chars[j]=chars[mask];
chars[mask]=t;
}
rep(i,0,chars.length()-1) S[i]=chars[i];
S[chars.length()]=0;
}
int main(){
sam.init();
int q;
scanf("%d",&q);
scanf("%s",S);
int n=strlen(S);
rep(i,0,n-1) sam.extend(S[i]-'A');
char op[10];
int mask=0,ans;
while (q--){
scanf("%s",op);
gets(mask);
if (op[0]=='Q'){
ans=sam.ask();
printf("%d\n",ans);
mask^=ans;
} else {
n=strlen(S);
rep(i,0,n-1) sam.extend(S[i]-'A');
}
}
return 0;
}
以及这题的迷之造数据程序
#include<cstdio>
#include<algorithm>
#define rep(a,b,c) for (int a=b;a<=c;a++)
using namespace std;
int main(){
freopen("1.in","w",stdout);
srand(time(0));
int n=10000;
printf("%d\n",n);
do putchar('A'+rand()%2); while (rand()%10); puts("");
while (n--){
printf(rand()%2?"QUERY ":"ADD ");
do putchar('A'+rand()%2); while (rand()%10); puts("");
}
return 0;
}