后缀数组刷题

  • 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;
    }
posted @ 2021-08-24 10:28  u_yan  阅读(28)  评论(0编辑  收藏  举报