版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
:最长公共前缀
:代表后缀在 后缀数组中的下标
:后缀 和后缀 的最长公共前缀
对于两个后缀 和 ,不妨设 ,不难得出后缀 和后缀 的长度等于
按照定义计算需要,整个height 数组需要。但是我们有的算法,我们用一个辅助数组,然后按照顺序递推计算。递推计算的基于一个性质:。
设排在后缀前一个是后缀。后缀和后缀分别删除首字符之后得到后缀和后缀 ,因此后缀一定排在后缀前面,并且最长公共前缀为。
这个是一系列 值中的最小值,这些 值中包括后缀和排在它前一个的后缀 的长度,即。因此。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000000 + 7;
char s[maxn];
int sa[maxn], c[maxn], x[maxn], y[maxn], n, m;
int Rank[maxn], height[maxn];
// LCP rank[i] 后缀 i 的排名, height[i] = LCP(sa[i-1], sa[i])
int d[maxn][32]; // d[i][j] 以 i 开始长度为 2^j 的区间的最值
int suffixArray() // 后缀数组
{
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 = 2; 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;
for(int i = 1; i <= m; i++) c[i] = 0;
for(int i = 1; i <= n; i++) ++c[x[i]];
for(int i = 2; i <= m; i++) c[i] += c[i-1];
for(int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i], y[i] = 0;
swap(x, y);
num = 1, x[sa[1]] = 1;
for(int i = 2; i <= n; i++) {
x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1] + k] == y[sa[i] + k]) ? num : ++num;
}
if(num >= n) break;
m = num;
}
return 0;
}
void getHeight()
{
int k = 0;
// sa[i] 排名为 i 的后缀的下标
// Rank[i] 后缀 i 的排名
for(int i = 1; i <= n; i++) Rank[sa[i]] = i;
for(int i = 1; i <= n; i++) {
if(k) k--;
int j = sa[Rank[i]-1];
while(s[i+k] == s[j+k]) k++;
height[Rank[i]] = k;
}
}
void RMQ_init(int* a, int n) // RMQ 初始化
{
// height数组是从1开始的,而RMQ的数组是从0开始的
for(int i = 0; i < n; i++) a[i] = a[i+1];
for(int i = 0; i < n; i++) d[i][0] = a[i];
for(int j = 1; (1 << j) <= n; j++) {
for(int i = 0; i + (1 << j) - 1 < n; i++) {
d[i][j] = min(d[i][j-1], d[i + (1 << (j-1))][j-1]);
}
}
}
int RMQ(int l, int r) // RMQ
{
int k = 0;
while((1 << (k + 1)) <= r - l + 1) k++;
return min(d[l][k], d[r-(1<<k)+1][k]);
}
int main()
{
while(scanf("%s", s + 1) == 1) {
n = strlen(s + 1);
m = 122;
suffixArray();
getHeight();
RMQ_init(height, n);
int l, r;
scanf("%d %d", &l, &r);
printf("%d\n", RMQ(l, r));
}
return 0;
}