字符串hash+排序+二分
字符串hash+排序+二分
\140. 后缀数组
复杂度O(\(n^2log n\))
排序就是题目里的按照字典序把字符串s的所有后缀排序,二分最长公共前缀。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char s[300010];
int sa[300010], n;
unsigned long long p[300010], f[300010];
int len(int a, int b) {
if(s[a] != s[b]) return 0;
int l = 0, r = n - max(a, b);
while(l < r) {
int mid = (l + r + 1) / 2;
if(f[a+mid] - f[a-1] * p[mid + 1] == f[b+mid] - f[b-1] * p[mid + 1]) {
l = mid;
}
else r = mid - 1;
}
return l + 1;
}
bool cmp(int a, int b) {
int l = len(a, b);
return s[a+l] < s[b+l];
}
int main() {
scanf("%s", s+1);
n = strlen(s+1);
p[0] = 1;
for(int i = 1; i <= n; i++) {
sa[i] = i;
p[i] = p[i-1] * 131;
f[i] = f[i-1] * 131 + s[i] - 'a' + 1;
}
sort(sa + 1, sa + 1 + n, cmp);
for(int i = 1; i <= n; i++) {
printf("%d", sa[i] - 1);
if(i == n) printf("\n");
else printf(" ");
}
printf("0 ");
for(int i = 2; i <= n; i++) {
printf("%d", len(sa[i], sa[i-1]));
if(i == n) printf("\n");
else printf(" ");
}
return 0;
}