AC自动机
贴一个模板题的代码:
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int M = 1000005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n;char s[M];
struct Automaton
{
int c[M][26],val[M],fail[M],cnt;
void ins(char *s)
{
int len=strlen(s),now=0;
for(int i=0;i<len;i++)
{
int v=s[i]-'a';
if(!c[now][v]) c[now][v]=++cnt;
now=c[now][v];
}
val[now]++;
}
void build()
{
queue<int> q;
for(int i=0;i<26;i++) if(c[0][i]) q.push(c[0][i]);
while(!q.empty())
{
int t=q.front();
q.pop();
for(int i=0;i<26;i++)
if(c[t][i]) fail[c[t][i]]=c[fail[t]][i],q.push(c[t][i]);
else c[t][i]=c[fail[t]][i];
}
}
int query(char *s)
{
int len=strlen(s),now=0,ans=0;
for(int i=0;i<len;i++)
{
now=c[now][s[i]-'a'];
for(int k=now;k&&~val[k];k=fail[k])
if(val[k]>=0)
ans+=val[k],val[k]=-1;
}
return ans;
}
}AC;
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
scanf("%s",s);
AC.ins(s);
}
AC.build();
scanf("%s",s);
printf("%d\n",AC.query(s));
}
后缀数组
贴一个模板题的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int M = 1000005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,m,x[M],y[M],c[M],sa[M],rk[M];
char s[M];
void get_sa()
{
for(int i=1;i<=n;i++) ++c[x[i]=s[i]];
for(int i=2;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i>=1;i--) sa[c[x[i]]--]=i;
for(int k=1;k<=n;k<<=1)
{
int num=0;
for(int i=n-k+1;i<=n;i++) y[++num]=i;
for(int i=1;i<=n;i++) if(sa[i]>k) y[++num]=sa[i]-k;
for(int i=1;i<=m;i++) c[i]=0;
for(int i=1;i<=n;i++) ++c[x[i]];
for(int i=2;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i>=1;i--) sa[c[x[y[i]]]--]=y[i],y[i]=0;
swap(x,y);
x[sa[1]]=1;num=1;
for(int i=2;i<=n;i++)
x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
if(num==n) break;
m=num;
}
for(int i=1;i<=n;i++) printf("%d ",sa[i]);
}
int main()
{
scanf("%s",s+1);
n=strlen(s+1);m=122;
get_sa();
}
后缀自动机
贴一道模板题的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int M = 2000005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,cnt=1,last=1,tot,val[M],f[M];
char s[M];long long ans;
struct node
{
int len,fa,ch[26];
node() {memset(ch,0,sizeof ch);len=fa=0;}
}a[M];
struct edge
{
int v,next;
edge(int V=0,int N=0) : v(V) , next(N) {}
}e[2*M];
void add(int c)
{
int p=last,np=last=++cnt;val[cnt]=1;
a[np].len=a[p].len+1;
for(;p && !a[p].ch[c];p=a[p].fa) a[p].ch[c]=np;
if(!p) a[np].fa=1;
else
{
int q=a[p].ch[c];
if(a[q].len==a[p].len+1) a[np].fa=q;
else
{
int nq=++cnt;
a[nq]=a[q];a[nq].len=a[p].len+1;
a[q].fa=a[np].fa=nq;
for(;p && a[p].ch[c]==q;p=a[p].fa) a[p].ch[c]=nq;
}
}
}
void link(int u,int v)
{
e[++tot]=edge(v,f[u]),f[u]=tot;
e[++tot]=edge(u,f[v]),f[v]=tot;
}
void dfs(int u,int fa)
{
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==fa) continue;
dfs(v,u);
val[u]+=val[v];
}
if(val[u]!=1) ans=max(ans,1ll*val[u]*a[u].len);
}
int main()
{
scanf("%s",s);
n=strlen(s);
for(int i=0;i<n;i++) add(s[i]-'a');
for(int i=2;i<=cnt;i++) link(i,a[i].fa);
dfs(1,0);
printf("%lld\n",ans);
}
回文自动机
跟AC自动机很像,转载某巨佬的博客。
贴一道模板题的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int M = 2000005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
struct node
{
int fail,len,num,ch[26];
node() {memset(ch,0,sizeof ch);fail=len=num=0;}
};
struct Pam
{
node b[M];char c[M];
int n,len,last,cnt,s[M];
Pam()
{
b[0].fail=1;b[1].len=-1;
cnt=1;last=0;
}
void read()
{
scanf("%s",c+1);
len=strlen(c+1);
}
int get_fail(int x)
{
while(s[n-b[x].len-1]^s[n])
{
x=b[x].fail;
}
return x;
}
void ins()
{
int p=get_fail(last);
if(!b[p].ch[s[n]])
{
b[++cnt].len=b[p].len+2;
int tmp=get_fail(b[p].fail);
b[cnt].fail=b[tmp].ch[s[n]];
b[cnt].num=b[b[cnt].fail].num+1;
b[p].ch[s[n]]=cnt;
}
last=b[p].ch[s[n]];
}
void solve()
{
int k=0;
s[0]=26;
for(n=1;n<=len;n++)
{
c[n]=(c[n]-97+k)%26+97;
s[n]=c[n]-'a';
ins();
printf("%d ",b[last].num);
k=b[last].num;
}
}
}P;
int main()
{
P.read();
P.solve();
}