后缀数组

140. 后缀数组(hash + 二分 / 后缀数组)

不打扰是莪最后的温柔 提交于 2019-11-26 14:33:53
题目链接 : https://www.acwing.com/problem/content/description/142/ Hash + 二分 #include <bits/stdc++.h> using namespace std; const int maxn = 3e5 + 7; typedef unsigned long long ull; const ull mod = 131; ull p[maxn],h[maxn]; int sa[maxn],rank[maxn],height[maxn]; char str[maxn]; int n ; ull get(int x,int y){ return h[y] - h[x - 1] * p[y - x + 1]; } int lcp(int x,int y){ int l = 0 ,r = min(n - x + 1,n - y + 1); while(l < r){ int mid = (l + r + 1) >> 1; if(get(x,x + mid - 1) != get(y,y + mid - 1)) r = mid - 1; else l = mid; } return l; } bool cmp(int x , int y){ int l = lcp(x,y); int av = x + l > n ?

后缀数组入门题

五迷三道 提交于 2019-11-26 11:10:36
先上da算法(n*logn)求height的板子: 注意:height的有效值是2-n,sa的有效值是1-n,rank的有效值是0-n-1.    str 转成 r的时候,是从第0位到n位,最后的\0也带上,不然会RE const int MAXN=2e3+5; int t1[MAXN], t2[MAXN], c[MAXN]; bool cmp(int *r, int a, int b, int l){ return r[a]==r[b] && r[a+l]==r[b+l]; } void da(int str[], int sa[], int rk[], int height[], int n, int m) { n++; int i, j, p, *x=t1, *y=t2; for(i=0; i<m; i++) c[i]=0; for(i=0; i<n; i++) c[x[i]=str[i]]++; for(i=1; i<m; i++) c[i]+=c[i-1]; for(i=n-1; i>=0; i--) sa[--c[x[i]]]=i; for(j=1; j<=n; j<<=1) { p=0; for(i=n-j; i<n; i++) y[p++]=i; for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0; i<m

后缀自动机

泪湿孤枕 提交于 2019-11-26 10:29:48
https://oi-wiki.org/string/sam/#_5 oiwiki网上的 https://blog.csdn.net/thy_asdf/article/details/51569443 这个博客讲了很多题。 //#include<bits/stdc++.h> #include<cstdio> #include<cstring> #include<queue> #include<vector> #include<algorithm> using namespace std; const int maxn = 2e4 + 5; const int maxc = 180;//如果太大可以用map const int mod = 1e9 + 7; const int inf = 0x3f3f3f3f; typedef long long ll; int len[maxn * 2]; //最长子串的长度(该节点字串数量=len[x]-len[fail[x]]) int fail[maxn * 2]; //后缀链接(最短串前部减少一个字符所到达的状态) int cnt[maxn * 2]; //被后缀连接的数量,方法一求拓扑排序时需要。 int nex[maxn * 2][maxc]; //状态转移(尾部加一个字符的下一个状态)(图),如果不只是字母,而是很大的话可以用map.

后缀数组习题集

∥☆過路亽.° 提交于 2019-11-26 09:59:26
suffix(i):从第i个字符开始的后缀 sa[i]:后缀数组,“排第几的是谁”,即suffix(sa[i])<suffix(sa[i+1]),1<=i<n。 ra[i]:名次数组,“你排第几”,ra[i]表示的是suffix(i)在所有后缀中从小到大排列的“名次” height[i]:suffix(sa[i-1])和suffix(sa[i])的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀。 对于j和k,设rank[j]<rank[j],则有: suffix(j)和suffix(k)的最长公共前缀为height[ra[j]+1],height[ra[j]+2],height[ra[j]+3],...,height[rank[k]]中的最小值。 1、 洛谷 P3809 【模板】后缀排序 参考 这里 ,以后求后缀数组都用倍增法吧。 1 #include<iostream> 2 #include<sstream> 3 #include<fstream> 4 #include<algorithm> 5 #include<cstring> 6 #include<iomanip> 7 #include<cstdlib> 8 #include<cctype> 9 #include<vector> 10 #include<string> 11 #include<cmath> 12

【模板】poj2774后缀数组

≡放荡痞女 提交于 2019-11-26 08:59:44
也是白书上来的,白书开了个专题后缀数组,然而这方面我完全不知道。。。于是在今天七夕节来学了一波后缀数组。。。。然后看了一个下午才看懂。。。网上各路大佬的代码我都有看,这里就表明一下主要的转载出处吧: 这一份是让我从不会到会的 : https://www.cnblogs.com/--zz/p/11144860.html 这一个是学height数组的:https://www.cnblogs.com/wsy01/p/6935135.html 这一个是打poj模板题的:https://blog.csdn.net/jeremy1149/article/details/52611995 poj:https://vjudge.net/problem/POJ-2774 说说我的看法吧。 1.sa数组和rnk数组就是一个互逆,原字符串的后缀子串的排名。 2、求sa数组用的是倍增,也就是我一开始不是直接求后缀的,我是求长度为k的子串的排名,在推到k+1的排名的,具体用到基数排序来做。 3.得出来的rnk是从0开始的,注意这一点。然后基数排序时注意有个倒序,具体原因就是旧的sa数组是之前排第二关键字来的,所以得sa数组大的先排,这个yy一下就好了。。 4、然后在求sa的过程中,m(也就是桶的大小是可以优化一下的)。 5.height数组我这里写得是h,h[i]代表着排名为i的后缀子串和排名i