后缀自动机模板(初步)

  看了几天居然连后缀自动机的构造原理和性质都没完全搞懂。。。更不用说应用了。

  在这里膜一下先辈CLJ大神(的PPt),大神的世界就是不懂。另外还要膜一下国家集训队的几篇论文作者,表示还没看懂orz

  先贴一个讲得通俗易懂的后缀自动机学习网站(蒟蒻的我居然仍然没看懂),讲得也够详细。学习网站

  苦逼的我·一个下午就死记硬背了这篇代码。感觉:看代码比看论文里的长篇大论简单多了(我是蒟蒻)。

  代码贴上(终于背下来了):

 1 #include<cstdio>
 2 #include<string.h>
 3 #define maxn 100000
 4 #define Len 10000
 5 using namespace std;
 6
 7 struct suffix_automaton
 8 {
 9     struct sufnode
10     {
11         long son[26],pre,len;
12     }suf[maxn];
13     long last,tot;
14     char s[Len];
15
16     inline void push(long len)
17     {
18         suf[++tot].len=len,suf[tot].pre=0;
19         memset(suf[tot].son,0,sizeof(suf[tot].son));
20     }
21
22     void Extend(char cc)
23     {
24         long q,nq,p,np;
25         push(suf[last].len+1);
26         p=last,np=tot;
27         for(;!suf[p].son;p=suf[p].pre)suf[p].son[ch]=np;
28         if (!p)suf[np].pre=0;
29             else {
30                 q=suf[p].son[ch];
31                 if (suf[q].len!=suf[p].len+1){
32                     push(suf[p].len+1);
33                     nq=tot;
34                     memcpy(suf[nq].son,suf[q].son,sizeof(suf[q].son));
35                     suf[nq].pre=suf[q].suf;
36                     suf[q].pre=suf[np].pre=nq;
37                     for (;suf[p].son[ch]==q;p=suf[p].pre)suf[p].son[ch]=nq;
38                 } else suf[np].pre=q;
39             }
40         last=np;
41     }
42
43     void Build()
44     {
45         long i,len;
46         scanf("%s",s);
47         tot=last=0;
48         for (i=0,len=s.size();i<len;i++)Extend(s[i]-‘A‘);
49     }
50 }suf;

  下面是CLJ的PPT

时间: 2024-09-30 00:27:22

后缀自动机模板(初步)的相关文章

hdu4622(后缀自动机模板)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意: 先输入一个长度为 n 的字符串, 然后有 q 个形如 l, r 的询问, 对于每个询问输出区间 [l, r] 中有多少不同的子串 思路: 后缀自动机模板 代码: 1 // 后缀自动机要理解其含义,从起点到每个点的不同路径,就是不同的子串. 2 // 到每一个点,不同路径,其实就是以这个点为最后一个字符的后缀,长度是介于(p->fa->len,p->len]之间的,个数也就清楚

广义后缀自动机模板

后缀自动机能解决很多单串的问题.但是一旦到了多串的情况.可能就会变得有些棘手 这个时候你可能会想能不能将多个串一起构建出和单串后缀自动机那样子拥有诸多优美性质的自动机呢? 答案当然是有的.那就是广义后缀自动机 对于广义后缀自动机.和普通的后缀自动机写法上有些许不同之处 大致就是在插入新串的时候.需要把当前状态指针 last 指回 root 还有一个问题.网上的人们都说广义后缀自动机在新插入节点的时候要判是否已经存在 这个就造成了代码的迥异 关于代码.借鉴了这个博客 ==> Click here

POJ 1509 Glass Beads 后缀自动机 模板 字符串的最小表示

http://poj.org/problem?id=1509 后缀自动机其实就是一个压缩储存空间时间(对节点重复利用)的储存所有一个字符串所有子串的trie树,如果想不起来长什么样子可以百度一下找个图回忆,从0开始到任意一个点的串都是字符串的子串. 有一些很好用的性质. 字符串的最小表示就是把一个字符串首尾相连再从任意一个地方断开产生的字典序最小的字符串,这个题是求最小表示的开头字母在原字符串中的下标(从1开始). 具体看实现吧,没什么可以解释的地方. 1 #include<iostream>

【模板】广义后缀自动机模板

建立在tire上的后缀自动机,采用bfs的建图方式,可以保证复杂度 #include<bits/stdc++.h> using namespace std; #define fu(a,b,c) for(int a=b;a<=c;++a) #define fd(a,b,c) for(int a=b;a>=c;--a) #define MAXN 2000010 #define LL long long const int CHARSET_SIZE=10; //Suffix_Automa

后缀自动机模板——不同子串个数p2408

后缀自动机的入门博客 https://www.luogu.org/blog/Kesdiael3/hou-zhui-zi-dong-ji-yang-xie 有两种求法,分别对应了两种性质 #include<bits/stdc++.h> using namespace std; #define maxn 200005 char s[maxn]; int n; int cmp(int a,int b); struct SAM{ int cnt,last; int nxt[maxn][26]; int

不在B中的A的子串数量 HDU - 4416 (后缀自动机模板题目)

题目: 给定一个字符串a,又给定一系列b字符串,求字符串a的子串不在b中出现的个数. 题解: 先将所有的查询串放入后缀自动机(每次将sam.last=1)(算出所有子串个数) 然后将母串放入后缀自动机然后记录这个子串个数 两个值相减即可 1 #include <set> 2 #include <map> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <

后缀自动机 模板

SAM板子,没什么好说的 建出来SAM然后跑个DFS统计答案就行了 1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define ll long long 6 #define N 3010 7 #define rint register int 8 #define il inline 9 #define idx(x) (x-'a'+1)

51nod1469 淋漓字符串(后缀自动机)

题目大意: 首先,我们来定义一下淋漓尽致子串. 1.令原串为S. 2.设子串的长度为len,在原串S中出现的次数为k,令其出现的位置为p1, p2, ....pk(即这个子串在原串中[pi,pi + len - 1]中出现). 3.若k=1,则该子串不是淋漓尽致子串. 4.若存在pi,pj(i != j),使得S[pi - 1] = S[pj - 1],则该子串不是淋漓尽致子串. 5.若存在pi,pj(i != j),使得S[pi + len] = S[pj + len],则该字串不是淋漓尽致字

CodeForces-204E:Little Elephant and Strings (后缀自动机)

The Little Elephant loves strings very much. He has an array a from n strings, consisting of lowercase English letters. Let's number the elements of the array from 1 to n, then let's denote the element number i as ai. For each string ai (1 ≤ i ≤ n) t