太弱了QAQ学完SAM这么久才学会构建QAQ
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 200010
using namespace std;
struct sam
{
int p,q,np,nq;
int cnt,last;
int a[MAXN][26],len[MAXN],fa[MAXN];
sam()
{
last = ++cnt;
}
void insert(int ch)
{
p = last;np = last = ++cnt;l[np] = l[p] + 1;
//不断添加从当前状态到np的转移,直到发现一个状态p已经存在关于字符ch的转移,转以后状态为q
while (!a[p][ch] && p) a[p][ch] = np,p = fa[p];
if (!p) fa[np] = 1;//有可能这个状态是自动机的初始状态
else
{
q = a[p][ch];//状态q为状态p经ch转移后得到的状态
//进行讨论,有len_q=len_p+1,len_q>len_p+1两种情况.
if (len[q] == len[p] + 1) fa[np] = q;//此时直接令fa_np=q
else
{
nq = ++cnt;len[nq] = len[p] + 1;//否则建立新状态nq,len_nq=len_p+1
//nq代表原来串中长度不超过len_p+1的串,其fa和转移都和q一致
memcpy(a[nq],a[q],sizeof(a[q]));
fa[nq] = fa[q];
fa[np] = fa[q] = nq;
while (a[p][ch] == q) a[p][ch]=q,p=fa[p];
}
}
}
void build()
{
char ch[MAXN];
scanf("%s",ch);
for (int i = 0;i < strlen(ch);i++) insert(ch[i] - ‘a‘);//对已知串构建后缀自动机
}
}
/*
int main()
{
}*/
我的代码注释一向很够看>_<
可以看到SAM在构建的时候是不断插入字符来构建的
也正因为这种方式,SAM能够做到别的字符串数据结构支持不了的在线插入字符
这也给了我们一个提示:
如果你面对一个字符串的题,模板串会在线插入字符或者题目要求强制在线,而数据范围又告诉你不能够通过重新预处理来更新出新版本的数据结构,那这个题必定是SAM无疑了.
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/creationaugust/article/details/47041971