博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
后缀自动机
阅读量:6153 次
发布时间:2019-06-21

本文共 2366 字,大约阅读时间需要 7 分钟。

特征

1、对于每个节点,父节点的接受串是该节点的接受串的后缀,而且是最长的那个。用该节点的len减去父节点的fa.len,就是该节点表示的串中父节点不能表示的串个数。

同理,当插入这个节点,出现的新不同子串个数就是len-fa.len。

2、每个节点表示串出现的次数,是这个节点子树上有效节点的总数。(有效节点指插入该字符产生的那个节点,也就是代码中extend中的clone节点)。

这样我们初始化有效节点为1,然后拓扑排序dp,就可以O(n)得到每个节点出现次数。

3、后缀自动机是一张有向无环图,其中顶点是状态,而边代表了状态之间的转移。

4、任意路径“匹配”某一子串,该子串由路径中边的标记组成。

5、如果程序中所处理字符串的最大可能长度是MAXN,那么至多会占用2*MAXN-1个状态。

6、由长度为n的字符串s建立的后缀自动机中,转移的数量不超过3n-4(对于n>=3)。

模板

1 #include
2 #include
3 using namespace std; 4 const int maxn = 1e5 + 10; 5 struct node 6 { 7 int ch[26], par,len; 8 }SA[maxn*2]; 9 int sz, root, last; 10 void init() 11 { 12 sz = root = last = 0; 13 SA[0].len = 0; 14 SA[0].par = -1; 15 memset(SA[0].ch, 0, sizeof(SA[0].ch)); 16 } 17 18 void extend(int c) 19 {
//向当前字符串的尾部添加一个字符 20 int p = last, cur = ++sz; 21 SA[cur].len = SA[p].len + 1; 22 for (; p!=-1 && !SA[p].ch[c]; p = SA[p].par) SA[p].ch[c] = cur; 23 if (p == -1) SA[cur].par = root; 24 else 25 { 26 int q = SA[p].ch[c]; 27 if (SA[q].len == SA[p].len + 1) SA[cur].par = q; 28 else 29 { 30 int clone = ++sz; 31 SA[clone] = SA[q]; 32 SA[clone].len = SA[p].len + 1; 33 SA[q].par = SA[cur].par = clone; 34 for (; p != -1 && SA[p].ch[c] == q; p = SA[p].par) SA[p].ch[c] = clone; 35 } 36 } 37 last = cur; 38 } 39 int encode(char c) 40 { 41 return c - 'a'; 42 } 43 int Count_substrings() 44 {
//不同子串的个数 45 int ans = 0; 46 for (int i = 1; i <= sz; i++) 47 { 48 ans += SA[i].len - SA[SA[i].par].len; 49 } 50 return ans; 51 } 52 bool find_substring(int*des, int n) 53 {
//寻找子串是否存在 54 int i=0, cur = SA[root].ch[des[0]]; 55 while (i < n&&cur) 56 { 57 i++; 58 cur = SA[cur].ch[des[i]]; 59 } 60 if (i == n) return true; 61 else return false; 62 } 63 int r[maxn<<2],w[maxn]; 64 void RadixSort(int n) 65 {
//拓扑排序 66 for(int i=0;i<=n;i++) w[i]=0; 67 for(int i=1;i<=sz;i++) w[SA[i].len]++; 68 for(int i=1;i<=n;i++) w[i]+=w[i-1]; 69 for(int i=sz;i>=1;i--) r[w[SA[i].len]--]=i; 70 r[0]=0; 71 } 72 int LCS(int*P,int lenP) 73 {
//求串P与建立后缀自动机的串的最长公共子串 74 int lcs=0,now=0,ans=0; 75 for(int i=0;i
View Code

 

转载于:https://www.cnblogs.com/ivan-count/p/9485922.html

你可能感兴趣的文章
MySQL的字符集和字符编码笔记
查看>>
ntpd同步时间
查看>>
must implement java.io.Serializable hessian
查看>>
Microsoft Licenses Flash Lite for Windows Mobile Users
查看>>
HDOJ 2020 绝对值排序
查看>>
HDOJ/HDU 2560 Buildings(嗯~水题)
查看>>
Maven编译时跳过Test
查看>>
Spring Boot 整合Spring Security 和Swagger2 遇到的问题小结
查看>>
[20170628]12C ORA-54032.txt
查看>>
除以2
查看>>
高可用集群原理解析
查看>>
Nginx配置URL转向tomcat
查看>>
极客Web前端开发资源大荟萃#001
查看>>
让div固定在某个位置
查看>>
Java开发环境Docker镜像
查看>>
从无到有,WebService Apache Axis2初步实践
查看>>
任务调度(一)——jdk自带的Timer
查看>>
UIKit框架(15)PCH头文件
查看>>
整理看到的好的文档
查看>>
Linux磁盘管理和文件系统管理
查看>>