KMP、AC自动机、后缀数组、后缀自动机、manacher、回文自动机
KMP
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e6+10;
int len1,len2,nt[maxn];
char s[maxn],c[maxn];
int main() {
scanf("%s%s",s+1,c+1);
len1=strlen(s+1);s[len1+1]=‘#‘;
len2=strlen(c+1);c[len2+1]=‘#‘;
int pos;
for(int i=2;i<=len2;++i) {
pos=nt[i-1];
while(pos&&c[pos+1]!=c[i]) pos=nt[pos];
nt[i]= c[pos+1]==c[i]? pos+1:0;
}
pos=0;
for(int i=1;i<=len1;++i) {
while(pos&&c[pos+1]!=s[i]) pos=nt[pos];
if(c[pos+1]==s[i]) pos++;
if(pos==len2) printf("%d\n",i-len2+1),pos=nt[pos];
}
for(int i=1;i<=len2;++i) printf("%d ",nt[i]);
return 0;
}
AC自动机(bzoj3530)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=1500+7;
const ll mod=1e9+7;
int n,m;
char s[maxn],d[maxn];
char cc;ll ff;
template<typename T>void read(T& aa) {
aa=0;ff=1; cc=getchar();
while(cc!=‘-‘&&(cc<‘0‘||cc>‘9‘)) cc=getchar();
if(cc==‘-‘) ff=-1,cc=getchar();
while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar();
aa*=ff;
}
void mo(ll &x){if(x>=mod) x-=mod;}
int fail[maxn],son[maxn][11],has[maxn],tot;
void insert() {
int len=strlen(s+1),now=0,x;
for(int i=1;i<=len;++i) {
x=s[i]-‘0‘;
if(!son[now][x]) son[now][x]=++tot;
now=son[now][x];
}
has[now]=1;
}
int zz[maxn];
void bld() {
int s=1,t=0,x;
for(int i=0;i<10;++i) if(son[0][i]) zz[++t]=son[0][i];
while(s<=t) {
x=zz[s++]; has[x]|=has[fail[x]];
for(int i=0;i<10;++i) {
if(son[x][i]) {
fail[son[x][i]]=son[fail[x]][i];
zz[++t]=son[x][i];
}
else son[x][i]=son[fail[x]][i];
}
}
}
ll f[maxn][maxn][4];
ll solve(int pos,int len,int p) {
if(has[pos]) return 0;
if(len>n) return 1;
if(~f[pos][len][p]) return f[pos][len][p];
ll rs=0;
if(p&2) rs+=solve(pos,len+1,p&2);
int l=p>>1,r=(p&1)? (d[len]-‘0‘):9;
for(int i=l;i<=r;++i) {
rs+=solve(son[pos][i],len+1,(p&1)&(i==d[len]-‘0‘));
mo(rs);
}
return f[pos][len][p]=rs;
}
int main() {
scanf("%s",d+1); n=strlen(d+1);
read(m);
for(int i=1;i<=m;++i) {
scanf("%s",s+1);
insert();
}
bld();
memset(f,-1,sizeof(f));
printf("%lld",(solve(0,1,3)-1+mod)%mod);
return 0;
}
/*
20
3
2
3
14
*/
后缀数组、manacher(0103练习题T3,和去年省选D2T3很像,但不用本质不同,而且简单很多,用后缀数组和马拉车预处理lcp和以i为开头的回文串(放到树状数组里))
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=16e5+10,INF=0x3f3f3f3f;
int n,m,Q,ql,qr;ll totans;
char A[maxn],B[maxn],S[2*maxn];
int x[maxn],y[maxn],c[maxn],sa[maxn],h[maxn],rad[maxn];
ll aa;char cc;
ll read() {
aa=0;cc=getchar();
while(cc<‘0‘||cc>‘9‘) cc=getchar();
while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar();
return aa;
}
ll minnum[4*maxn];
void bld(int pos,int l,int r) {
if(l==r) {
minnum[pos]=h[l];
return;
}
int mid=(l+r)>>1;
bld(pos<<1,l,mid); bld(pos<<1|1,mid+1,r);
minnum[pos]=min(minnum[pos<<1],minnum[pos<<1|1]);
}
ll qmin(int pos,int l,int r) {
if(l>=ql&&r<=qr) return minnum[pos];
int mid=(l+r)>>1;ll rs=INF;
if(ql<=mid) rs=min(rs,qmin(pos<<1,l,mid));
if(qr>mid) rs=min(rs,qmin(pos<<1|1,mid+1,r));
return rs;
}
ll tot[2][maxn],sum[2][maxn];
ll q(int pos,ll *sz) {
ll rs=0;
while(pos) {
rs+=sz[pos];
pos-=pos&-pos;
}
return rs;
}
void chge(int pos,int x,ll *sz,int n) {
while(pos<=n) {
sz[pos]+=x;
pos+=pos&-pos;
}
}
void get_sa(char *s,int n) {
int m=‘z‘+1,p;
for(int i=0;i<n;++i) c[x[i]=s[i]]++;
for(int i=1;i<m;++i) c[i]+=c[i-1];
for(int i=n-1;i>=0;--i) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1) {
p=0;
for(int i=n-1;i>=n-k;--i) y[p++]=i;
for(int i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k;
for(int i=0;i<m;++i) c[i]=0;
for(int i=0;i<n;++i) c[x[y[i]]]++;
for(int i=1;i<m;++i) c[i]+=c[i-1];
for(int i=n-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];
swap(x,y);p=1;
x[sa[0]]=0;
for(int i=1;i<n;++i)
x[sa[i]]= y[sa[i]]==y[sa[i-1]]&&
((sa[i]+k<n&&sa[i-1]+k<n&&y[sa[i]+k]==y[sa[i-1]+k])||(sa[i]+k>=n&&sa[i-1]+k>=n))? p-1:p++;
if(p>=n) break; else m=p;
}
p=0;int u;
for(int i=0;i<n;++i) {
if(!x[i]) continue;
u=sa[x[i]-1];
if(p) p--;
while(s[u+p]==s[i+p]) p++;
h[x[i]]=p;
}
memset(minnum,0x3f3f3f3f,sizeof(minnum));
bld(1,1,n-1);
}
void manacher(char *s,ll *sz,int len,int o) {
int maxpos=0,p=0;
for(int i=len;i;--i) {//不是从0开始而是从1开始
s[i<<1]=s[i];
s[i<<1|1]=‘#‘;
}
s[0]=s[1]=‘#‘;
for(int i=2;i<=2*len;++i) {
if(maxpos>i) rad[i]=min(maxpos-i,rad[2*p-i]);
else rad[i]=0;
while(i-rad[i]>0&&i+rad[i]<=2*len+1&&s[i-rad[i]]==s[i+rad[i]]) rad[i]++;
rad[i]--;
if(i+rad[i]>maxpos) p=i,maxpos=i+rad[i];
}
for(int i=2;i<=2*len;++i) {
chge((i-rad[i]+1)>>1,1,tot[o],len);
chge((i+2)>>1,-1,tot[o],len);
}
}
int main() {
freopen("palindrome.in","r",stdin);
freopen("palindrome.out","w",stdout);
scanf("%s",A+1);
scanf("%s%s",A+1,B+1);
n=strlen(A+1); m=strlen(B+1);
for(int i=1;i<=m/2;++i) swap(B[i],B[m-i+1]);
for(int i=1;i<=n;++i) S[i-1]=A[i]; S[n]=‘#‘;//n不是n+1
for(int i=1;i<=m;++i) S[i+n]=B[i];
get_sa(S,n+m+1);
manacher(A,tot[0],n,0);
manacher(B,tot[1],m,1);
for(int i=1;i<=n;++i) chge(i,q(i,tot[0]),sum[0],n+1);
for(int i=1;i<=m;++i) chge(i,q(i,tot[1]),sum[1],m+1);
//注意是n+1和m+1,因为可能询问到
Q=read();int xx,yy,len;
for(int i=1;i<=Q;++i) {
xx=read(); yy=read();
ql=x[xx-1]; qr=x[yy+n];
if(qr<ql) swap(ql,qr);
++ql;
len=qmin(1,1,n+m);
totans=len;
totans+=q(xx+len,sum[0])-q(xx,sum[0]);
totans+=q(yy+len,sum[1])-q(yy,sum[1]);//注意边界
printf("%lld\n",totans);
}
fclose(stdin);fclose(stdout);
return 0;
}
/*
orzAchen
babaabbba
baaabbb
1
9 6
*/
后缀自动机(bzoj2555 LCT+SAM)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define lc son[pos][0]
#define rc son[pos][1]
const int maxn=1200000+7;
int mask,n,m,ans;
char s[maxn];
string chars;
char cc;ll ff;
template<typename T>void read(T& aa) {
aa=0;ff=1; cc=getchar();
while(cc!=‘-‘&&(cc<‘0‘||cc>‘9‘)) cc=getchar();
if(cc==‘-‘) ff=-1,cc=getchar();
while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar();
aa*=ff;
}
void gets(int mask)
{
scanf("%s",s);
chars=s; int len=chars.length();
for(int j=0;j<len;j++)
{
mask=(mask*131+j)%len;
char t=chars[j];
chars[j]=chars[mask];
chars[mask]=t;
}
}
struct Lct{
int fa[maxn],son[maxn][2],w[maxn],laz[maxn],zz[maxn],t;
void pd(int pos) {
if(!laz[pos]) return;
if(lc) laz[lc]+=laz[pos],w[lc]+=laz[pos];
if(rc) laz[rc]+=laz[pos],w[rc]+=laz[pos];
laz[pos]=0;
}
bool isroot(int pos) {
return son[fa[pos]][0]!=pos&&son[fa[pos]][1]!=pos;
}
void rotate(int pos) {
int x,y,p,t; y=fa[x=fa[pos]];t=isroot(x);
p=son[x][1]==pos;
son[x][p]=son[pos][!p]; fa[son[pos][!p]]=x;
son[pos][!p]=x; fa[x]=pos;
fa[pos]=y;
if(!t) son[y][son[y][1]==x]=pos;
}
void splay(int pos) {
t=0; int x,y;
for(x=pos;!isroot(x);x=fa[x]) zz[++t]=x;
zz[++t]=x;
while(t) pd(zz[t--]);
for(;!isroot(pos);rotate(pos)) {
y=fa[x=fa[pos]];
if(!isroot(x))
(son[x][1]==pos)^(son[y][1]==x)? rotate(pos):rotate(x);
}
}
void access(int pos) {
for(int t=0;pos;pos=fa[pos]) {
splay(pos);rc=t;
t=pos;
}
}
void lk(int x,int f) {
fa[x]=f; access(f); splay(f);
if(f) laz[f]+=w[x],w[f]+=w[x];
}
void cut(int pos) {
access(pos);splay(pos);
if(lc) laz[lc]-=w[pos],w[lc]-=w[pos];
fa[lc]=0; lc=0;
}
}lct;
struct Sam{
Sam* next[27],*par;
int step;
}pool[2*maxn],*root,*last;
int tot;
Sam* newnode(int step) {
Sam *t=pool+(tot++);
t->step=step;
t->par=NULL;
memset(t->next,0,sizeof(t->next));
return t;
}
void Extend(int w) {
// cout<<"Extend"<<w<<": ";
Sam *p=last;
Sam *np=newnode(p->step+1);lct.w[tot]=1;
int x,y;
for(;p&&!p->next[w];p=p->par) p->next[w]=np;
if(!p) {
np->par=root;
// cout<<"np link->root\n";
lct.lk(tot,1);
}
else {
Sam *q=p->next[w];x=q-pool+1;
if(q->step==p->step+1) {
np->par=q;
// cout<<"np link->q\n";
lct.lk(tot,x);
}
else {
Sam *nq=newnode(p->step+1);lct.w[tot]=0;
memcpy(nq->next,q->next,sizeof(q->next));
y=q->par-pool+1;
lct.cut(x);
nq->par=q->par;
q->par=nq; lct.lk(x,tot);
np->par=nq;lct.lk(tot-1,tot);
lct.lk(tot,y);
// cout<<"nq linked by q&np\n";
for(;p&&p->next[w]==q;p=p->par) p->next[w]=nq;
}
}
last=np;
}
void add() {
gets(mask);
int len=chars.length();
for(int i=0;i<len;i++)
Extend(chars[i]-‘A‘);
}
int q(){
gets(mask);int x;
int len=chars.length();Sam *now=root;
for(int i=0;i<len;i++)
if(!(now=now->next[chars[i]-‘A‘])) return 0;
lct.splay(x=now-pool+1);
return lct.w[x];
}
int main() {
read(m);
scanf("%s",s+1);
n=strlen(s+1);
last=root=newnode(0);
for(int i=1;i<=n;++i) Extend(s[i]-‘A‘);
for(int i=1;i<=m;++i) {
scanf("%s",s);
if(s[0]==‘A‘) add();
else {
ans=q();
printf("%d\n",ans);
mask^=ans;
}
}
return 0;
}
/*
4
A
ADD BBABBBBAAB
QUERY ABA
ADD BBABAB
QUERY BAAB
*/
回文自动机留坑