题意:
给你一个长度为 $n$ 的字符串还有 $Q$ 个询问,对于每个询问给出一个 $k$ ,你要在这个字符串的所有子串中找到 $k$ 个串并且每个串都相同的方案数。
分析:
$cnt[i]$ 为出现过 $i$ 次的子串有多少个,那么答案就是 $\sum_{i=1}^{n}cnt[i]\times C(i,k)$
那么接下来的问题就是怎么计算 $cnt$ 数组了。
考虑用 $SA$,$sa$ 数组是已经把后缀排好序了,那么观察这些后缀,有相同前缀的肯定就挨在一起,所以我们按枚举后缀 $sa[i]$,然后从每个后缀的 $Height[i]$ 扫一遍。
假设现在枚举到长度 $j$,那么1
2
3
4if (Height[i + 1] <= j) {
cnt[1] += n - x - j + 1;
break;
}
注意我们已经对后缀排好序,那么这个时候往后的肯定只是出现一次。
否则1
2
3
4
5
6for (int k = i + 1; k <= n + 1; k++) {
if (Height[k] <= j) {
cnt[k - i]++;
break;
}
}
枚举排名在后面的后缀,前面说过,有相同前缀的就会挨在一起,那么当 $Height[k]$ 比 $j$ 小时,说明有相同前缀的后缀已经统计了,直接更新 $cnt$。
然后就是 $O(n^2)$ 处理 $ans[k]$ 了。
对于每个询问输出就可以了。
总的复杂度是 $O(n^2)$。
1 |
|