后缀数组

hdu 6704 后缀数组+主席树+RMQ

戏子无情 提交于 2019-11-29 01:05:21
给一个长为n的字符串,m次询问,每次求子串[l,r]第k次出现的起点位置 做法: 数据量很大,输入的字符串/询问总量可以达到1e5*5,必须尽量实现单次$O(logn)$的查询和至多$O(nlogn)$的预处理 1.子串[l,r]一定是某个后缀的前缀,而"后缀的前缀的重复出现"这个问题可以很容易想到后缀数组的height 2.考虑重复出现,显然一个后缀的长为r-l+1的前缀的出现位置即为height数组上一段连续的大于等于r-l+1的区间 3.得到这个区间后,就变成了一个在sa数组上求区间第k小的问题了 那么做法就是: 预处理: 1.预处理height数组 2.预处理height数组区间min的st表 3.预处理支持查询sa数组上的区间kth的 一棵可持久化线段树 处理询问: 1.我们从后缀数组的rk[l],直接锁定一个合法的起始位置, 2.然后利用st表快速二分出一个合法的连续区间,满足min>=r-l+1, 3.在可持久化线段树上查询这个区间的kth小 总复杂度:$O((m+n)logn)$ (说起来挺复杂,但是也就130行) #include<bits/stdc++.h> #define ll long long #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b)

hdu 4691 后缀数组+rmq 求子串lcp

落花浮王杯 提交于 2019-11-29 01:04:01
利用RMQ求子串lcp的基础题,这个板子是我之前的,比较蠢的一种实现 后面试试用最新的板子AC一下 #include<bits/stdc++.h> #define ll long long #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define per(ii,a,b) for(int ii=b;ii>=a;--ii) using namespace std; const int maxn=2e5+10,maxm=2e6+10; const ll INF=0x3f3f3f3f,mod=1e9+7; int casn,n,m,k; const int csize=131; char s[maxn]; class suffix{public: int sa[maxn],rank[maxn],h[maxn]; int wa[maxn],wb[maxn],wc[maxn],wd[maxn]; char *str; void geth(int n){ int i,j,k=0; for(i=1;i<=n;++i) rank[sa[i]]=i; for(i=0;i<n;h[rank[i++]]=k) for(k?k--:0,j=sa[rank[i]-1];str[i+k]==str[j+k];++k); } void getsa(char *_s

codeforces 873F 后缀数组+单调栈(fastio)

做~自己de王妃 提交于 2019-11-29 01:03:57
1.不能以某些位置结尾=不能以某些位置开头,于是倒转字符串 2.不考虑禁止的情况,则题目转化为height数组上求最大矩形,进行两次单调栈即可 3.考虑禁止的情况,实际上就等于计算次数的时候,减少合法区间内的1的个数 嗯,顺便存一下最终的fastio和后缀数组板子,以后应该不会再换了 #include<bits/stdc++.h> #define ll long long #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define per(ii,a,b) for(int ii=b;ii>=a;--ii) using namespace std;//head const int maxn=4e5+10,maxm=2e6+10; const ll INF=0x3f3f3f3f,mod=1e9+7; int casn,n,m,k,num[maxn]; namespace fastio{//@精简版,支持读取整数,字符串,输出整数@ bool isdecimal(char c){return (c >= 48 && c <= 57) || (c == 46);} bool isdigit(char c){return c >= 48 && c <= 57;} const int maxsz=10000000; class fast

J - Life Forms POJ - 3294 (后缀数组 + 二分)

落爺英雄遲暮 提交于 2019-11-28 21:52:10
You may have wondered why most extraterrestrial life forms resemble humans, differing by superficial traits such as height, colour, wrinkles, ears, eyebrows and the like. A few bear no human resemblance; these typically have geometric or amorphous shapes like cubes, oil slicks or clouds of dust. The answer is given in the 146th episode of Star Trek - The Next Generation , titled The Chase . It turns out that in the vast majority of the quadrant's life forms ended up with a large fragment of common DNA. Given the DNA sequences of several life forms represented as strings of letters, you are to

Common Substrings(后缀数组+单调栈)

﹥>﹥吖頭↗ 提交于 2019-11-28 19:51:37
https://cn.vjudge.net/problem/POJ-3415 A substring of a string T is defined as: T ( i , k )= TiTi +1... Ti+k -1, 1≤ i ≤ i+k -1≤| T |. Given two strings A , B and one integer K , we define S , a set of triples ( i , j , k ): S = {( i , j , k ) | k ≥ K , A ( i , k )= B ( j , k )}. You are to give the value of | S | for specific A , B and K . Input The input file contains several blocks of data. For each block, the first line contains one integer K , followed by two lines containing strings A and B , respectively. The input file is ended by K =0. 1 ≤ | A |, | B | ≤ 105 1 ≤ K ≤ min {| A |, | B |}

hdu3518 Boring counting(后缀数组)

こ雲淡風輕ζ 提交于 2019-11-28 18:34:58
Boring counting 题目传送门 解题思路 后缀数组。枚举每种长度,对于每个字符串,记录其最大起始位置和最小起始位置,比较是否重合。 代码如下 #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; const int N = 1005; char s[N]; int sa[N], x[N], y[N], c[N]; int n, m; void get_sa() { for(int i = 1; i <= m; i ++) c[i] = 0; for(int i = 1; i <= n; i ++) c[x[i] = s[i]] ++; for(int i = 1; i <= m; i ++) c[i] += c[i - 1]; for(int i = n; i >= 1; i --) sa[c[x[i]] --] = i; for(int k = 1; k <= n; k <<= 1){ int num = 0; for(int i = n - k + 1; i <= n; i ++) y[++num] = i; for(int i = 1; i <= n; i ++) if(sa[i] > k) y[++num] = sa[i] - k;

后缀数组简要总结

家住魔仙堡 提交于 2019-11-28 16:30:21
  众所周知,后缀数组是解决字符串类问题的强力工具,一切与字符串公共子串相关联的都可能与它有关。   方便起见,我们令   a为需要处理的子串(长度为len)(从a[1]开始到a[len])   rank[i]数组表示以i位置开始的后缀子串在所有后缀子串的字典序排名(以i位置开始的后缀子串即a[i]~a[len])   sa[i]数组表示排名为i的后缀子串的开始位置   根据定义很显然有 sa[rank[i]]=i,rank[sa[i]]=i   要先牢牢把握好这些数组的含义。 (来自网络的一张图)   后缀数组指的就是 sa[i] 数组啦,我们现在要想办法如何求 sa[i] 数组。   思考了下感觉直接求 sa[i] 数组非常复杂,因为排名什么的是要建立在求出所有后缀子串的前提下才求得出来。   注意到 sa[rank[i]]=i ,我们可以先求 rank[i] 数组,然后就可以知道 sa[i] 数组了。   很显然有一个 O(len 2 log len) 的算法,就是直接把 len 个长度为 O(len) 的字符串排序,但要是我们采用这个算法的话就没有下文了。    计算机芯片有一个特性,通用的芯片处理能力不高,但它可以处理很多信息,而专用的芯片处理能力就很强,但它只能处理单一方面的信息。   而上述算法正因为是通用,所以效率才不高。我们要提高效率,就要去研究所处理的数据的性质

pathinfo() PHP函数

ⅰ亾dé卋堺 提交于 2019-11-28 16:06:44
pathinfo() 以数组的形式返回关于文件路径的信息 返回的数组元素如下 [dirname]:文件路径 [basename]:文件名 [extension]:文件后缀 [filename]:不包含后缀的文件名 语法: path 必需。规定要检查的路径。 options 可选。规定要返回的数组元素。默认是 all。 可能的值: PATHINFO_DIRNAME - 只返回 dirname PATHINFO_BASENAME - 只返回 basename PATHINFO_EXTENSION - 只返回 extension PATHINFO_FILENAME - 只返回 filename 示例 输出 Array ( [dirname] => /11 [basename] => test.php [extension] => php [filename] => test ) 来源: https://www.cnblogs.com/rjbc/p/11414577.html

后缀数组的理解于模板

99封情书 提交于 2019-11-28 15:47:15
后缀数组主要是得出: sa[i]=pos ; 排名第i的是pos位置开始的 (这里用于排名的都是原串中以 不同位置 开始到 最后 的字符串按照 字典序 排序) height[i] 是 suffix(sa[i-1]) 和 suffix(sa[i]) 的最长公共前缀长度,即排名相邻的两个后缀的最长公共前缀长度。 原理可以参考: https://blog.csdn.net/a1035719430/article/details/80217267 https://www.cnblogs.com/victorique/p/8480093.html 代码解释: #include<iostream> #include<cstdio> #include<cstring> #define rint register int #define inv inline void #define ini inline int #define maxn 1000050 using namespace std; char s[maxn]; int y[maxn],x[maxn],c[maxn],sa[maxn],rk[maxn],height[maxn],wt[30]; int n,m; inv putout(int x) { if(!x) { putchar(48); return; } rint l=0;

后缀数组suffix array

烂漫一生 提交于 2019-11-28 15:39:16
自用模板: #include <iostream> #include <string.h> using namespace std; const int MAX_N=210000; char s[MAX_N]; int sa[MAX_N],t[MAX_N],t2[MAX_N],c[MAX_N],n; void build_sa(int m) { int i,*x=t,*y=t2; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=s[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(int k=1;k<=n;k<<=1) { int p=0; for(i=n-k;i<n;i++)y[p++]=i; for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[y[i]]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for(i=1;i<n;i++)x[sa[i]]