后缀自动机 板子
Posted ppprseter
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了后缀自动机 板子相关的知识,希望对你有一定的参考价值。
后缀自动机
并没有搞的很清楚,凭着当前的理解胡乱bb两句得了,内容存在误导,请仔细甄别。
endpos
集合每个子串结尾的位置集合。
本质相同
endpos
相等的子串集合然后这个本质不同的集合构成自动机的状态。
(substr(i)),状态(i)包含的子串集合
(len(i)),状态(i)包含的最长子串
性质:状态(i)包含的子串是最长子串长度连续的一段后缀。
后缀连接((parent)边)
状态(i)最小子串的后缀为什么不在里面呢?
因为在别的地方出现了后缀,被分到别的状态了。
那么当前状态对这个别的状态连边即是后缀连接。
构造流程(在线增量法)
新建一个点,然后走上一个点的parent边,如果状态未对当前连边,连上。
1步骤在根结束,par边连虚根1
1步骤在(p)结束
- 如果(p)的后面的点与(p)长度差一个,(par)指中国后面的点,这里没有产生新状态
- 不止差一个,(p)的末尾状态掉了,再开一个状态存一下,然后把东西继承一下,然后旧状态抵回去,最后新点再更新一下信息。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using std::max;
const int N=2e6+10;
int head[N],to[N],Next[N],cnt;
void add(int u,int v){to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;}
int tot=1,las=1,ch[N][26],siz[N],par[N],len[N],n;
ll ans;char s[N];
void extend(int c)
{
int now=++tot,p=las;
len[now]=len[las]+1,siz[now]=1;
while(p&&!ch[p][c]) ch[p][c]=now,p=par[p];
if(!p) par[now]=1;
else
{
int x=ch[p][c];
if(len[p]+1==len[x]) par[now]=x;
else
{
int y=++tot;
len[y]=len[p]+1,par[y]=par[x];
memcpy(ch[y],ch[x],sizeof(ch[x]));
while(p&&ch[p][c]==x) ch[p][c]=y,p=par[p];
par[now]=par[x]=y;
}
}
las=now;
}
void dfs(int now)
{
for(int i=head[now];i;i=Next[i])
dfs(to[i]),siz[now]+=siz[to[i]];
if(siz[now]>1) ans=max(ans,1ll*siz[now]*len[now]);
}
int main()
{
scanf("%s",s+1),n=strlen(s+1);
for(int i=1;i<=n;i++) extend(s[i]-'a');
for(int i=2;i<=tot;i++) add(par[i],i);
dfs(1);
printf("%lld
",ans);
return 0;
}
2019.1.4
以上是关于后缀自动机 板子的主要内容,如果未能解决你的问题,请参考以下文章