后缀树组(SA)初探

还没有什么任意两个后缀的LCP这些玩意儿。

启蒙题:输入一个串S,求最长的串T使得T在S中出现过不止一次。输出T的长度。

 1 #include <algorithm>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define N 100
 5 char s[N+1];
 6 int n, sa[N], rank[N], height[N];
 7 namespace SABuilder {
 8     int cnt[N], t1[N<<1], t2[N<<1];
 9     void work() {
10         int i, k, m = 26, p, *x = t1, *y = t2;
11         memset(cnt, 0, m * sizeof(int));
12         for(i = 0; i < n; ++i) ++cnt[x[i] = s[i] - ‘a‘];
13         for(i = 1; i < m; ++i) cnt[i] += cnt[i-1];
14         for(i = n - 1; i >= 0; --i) sa[--cnt[x[i]]] = i;
15         for(k = 1; k <= n; k <<= 1) {
16             for(i = n-k, p = 0; i < n; ++i) y[p++] = i;
17             for(i = 0; i < n; ++i) if(sa[i] >= k) y[p++] = sa[i] - k;
18             memset(cnt, 0, m * sizeof(int));
19             for(i = 0; i < n; ++i) ++cnt[x[y[i]]];
20             for(i = 1; i < m; ++i) cnt[i] += cnt[i-1];
21             for(i = n - 1; i >= 0; --i) sa[--cnt[x[y[i]]]] = y[i];
22             std::swap(x, y);
23             x[sa[0]] = 0;
24             for(i = m = 1; i < n; ++i) {
25                 x[sa[i]] = y[sa[i]]==y[sa[i-1]]&&sa[i]+k<n&&sa[i-1]+k<n&&y[sa[i]+k]==y[sa[i-1]+k] ? m-1 : m++;
26             }
27             if(m > n) break;
28         }
29         memcpy(rank, x, n * sizeof(int));
30         for(i = 0, p = 0; i < n; ++i) if(rank[i]) {
31             if(p) --p;
32             k = sa[rank[i]-1];
33             while(s[i+p] == s[k+p]) ++p;
34             height[rank[i]] = p;
35         }
36     }
37 }
38 int main() {
39     register int i, ans = 0;
40     gets(s);
41     n = strlen(s);
42     SABuilder::work();
43     printf("%d", ans);
44     return 0;
45 }
时间: 2024-10-11 21:27:39

后缀树组(SA)初探的相关文章

[whu1564]后缀树组

http://acm.whu.edu.cn/land/problem/detail?problem_id=1564 思路:先把串复制一遍,在末尾补个标记,后缀树组跑一下,扫一遍就ok了(过滤后缀在后半部分的). 1 #pragma comment(linker, "/STACK:10240000,10240000") 2 3 #include <iostream> 4 #include <cstdio> 5 #include <algorithm>

ural1297(后缀树组+rmq)

Palindrome 题意: 求给定字符串的最长回文子串. 分析: 首先想到的是求str与反序的str的最大公共子串,考虑abcdba这种情况,所以对于求出的公共子串判断一下是否是回文串即可.还有一种做法是枚举每一个字符为回文串的中间点,求出这个字符的后缀与前缀的最长公共子串就是回文串.对于前缀可以认为是反序str中对应字符的后缀,根据后缀树组中height数组的性质,suffix(i)和suffix(j)的最长公共前缀为height[rank[i]+1],height[rank[i]+2]--

K-th occurrence(后缀树组+划分树+ST表+RMQ+二分)

2019CCPC网络选拔赛1003 HDU6704 题目大意: T个测试样例.一个长度为N的字符串S,之后Q个[l,r,k],表示一个子串S[l,r],求出第k个该子串的下标.起始坐标为1.不存在输出-1. 数据范围:1≤T≤20,  1≤N≤105,  1≤Q≤105,  1≤l≤r≤N,  1≤k≤N,  |S|=N; 赛后补题.参考题解说后缀树组+划分树+ST表+二分. 比赛的时候只会后缀树组不会划分树,赛后仔细想,觉得后缀数组可以,然而并不,会TLE. 补提的时候先是采用后缀树组+划分树

POJ3581---Sequence 后缀树组

题意:n个数字组成的序列,第一个数字最大,,把序列分成3部分,每个部分分别翻转,输出翻转后字典序最小的序列.. 后缀数组变一下,,先求出 第一个分割的位置,,然后再求一次后缀数组,,求出第二个位置..输出就好了. 此题要采用单组输入... 1 #include <set> 2 #include <map> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <

HDU4436---str2int 后缀树组(12年天津区域赛)

str2int Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1568    Accepted Submission(s): 540 Problem Description In this problem, you are given several strings that contain only digits from '0'

[转载]字典树(trie树)、后缀树

(1)字典树(Trie树) Trie是个简单但实用的数据结构,通常用于实现字典查询.我们做即时响应用户输入的AJAX搜索框时,就是Trie开始.本质上,Trie是一颗存储多个字符串的树.相邻节点间的边代表一个字符,这样树的每条分支代表一则子串,而树的叶节点则代表完整的字符串.和普通树不同的地方是,相同的字符串前缀共享同一条分支.还是例子最清楚.给出一组单词,inn, int, at, age, adv, ant, 我们可以得到下面的Trie: 可以看出: 每条边对应一个字母. 每个节点对应一项前

【UOJ131/NOI2015D2T2-品酒大会】sam求后缀树

题目链接:http://uoj.ac/problem/131 题意:给出一个字符串,第i个字符对应的值为a[i], 对于i∈[0,n),求最长公共前缀大于等于i的字串对个数,并求这些字符串对开头对应值相乘最大值.n=3*10^5 题解: 学了个厉害的东西啊... 正解好像是sa+并查集(合并height) 然而我学了个用sam的做法.. 对于第一问: 首先我们要知道,建立后缀自动机之后,parent树就是逆序串的后缀树. why?看这个博客好了:http://z55250825.blog.163

利用后缀数组构造后缀树

由于蒟蒻azui前段时间忙着准备省选,并在省选中闷声滚大粗,博客停更了好久.. 省选过后整个人各种颓,整天玩玩泥巴什么的... 前段时间学后缀数组的时候上网查相关资料,看到说后缀数组和后缀树是可以相互转化的,并且uoj上有大量通过后缀自动机建出后缀树然后dfs遍历获得后缀数组的模板,但是通过后缀数组来建后缀树的资料确实稀缺. 也许大牛们都觉得这xjbYY一下就可以写了,所以网上没找到对应的代码,那么我来补个坑吧.大牛勿喷.. 先谈谈我的理解吧.. 讲道理后缀数组和后缀树应该是完全等价的,但前两者

关于广义后缀树(多串SAM)的总结

之前我们给的SAM的例题,基本上是一个串建SAM的就能做的 如果要建多个串的SAM应该怎么做呢 首先看题,bzoj2780 我一开始的想法是SA以前的弄法,把串拼起来,中间加分隔符做SAM 这题确实可以这么做,这样根据SAM能识别所有子串的性质 而且每个节点都代表了唯一的一个串 每个询问串我们都能找到最终转移到哪(找不到就是没出现过) 问在多少个串出现过这就等价于在ST(s)的parent树的子树中,出现了多少种不同的权值 这显然可以维护dfs序,用经典的离线做法来搞 1 type node=r