后缀数组刷题
-
P4051 [JSOI2007]字符加密
经典trick,很显然的是看到题目,就是后缀排序,然后如果你加一段原串到尾部,然后再进行后缀排序,会发现,\([1,n]\) 之间的后缀的相对位置关系没有发生变化,因为他们同时加上了相同的后缀,没有变化,所以直接排完序输出即可。 -
P2408 不同子串个数
首先一个字符串中子串数量是 \(\frac{n\times(n+1)}{2}\),其次所有后缀的前缀的集合就是所有字符串中子串的数量,那么就是去掉重复的,那么就是所有的height数组的和即为重复的子串。 -
Display Substring HDU - 6988
后缀数组,很显然,要二分找那个权值,然后 \(O(n \log(n))\) 的check,但是由于二分意外,导致调试了一上午,然后就是应该注意边界,二分区间里没有答案,应该特判。
bool check(int x) {
ll cnt = 0;
for (int i = 1;i <= n; i++) {
int l = SA[i], r = n, ans_pos = l;
while (l <= r) {
int mid = l + r >> 1;
if (sum[mid] - sum[SA[i]-1] <= x) {
ans_pos = mid;
l = mid + 1;
} else r = mid - 1;
}
if (sum[ans_pos] - sum[SA[i]-1] > x)ans_pos--;//!!!!!很关键,必须保证默认值ans_pos 是正确的,但是赋值的时候不一定ans_pos是正确的。
cnt += max(0, ans_pos - SA[i] + 1 - Height[i]);
}
return cnt < k;
}