题目背景
因为NOI被虐傻了,蒟蒻的YJQ准备来学习一下字符串,于是它碰到了这样一道题:
题目描述
给你一个长为$N$的字符串,求不同的子串的个数。
我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样。
子串的定义:原字符串中连续的一段字符组成的字符串。
输入输出格式
输入格式:
第一行一个整数$N$。
接下来一行$N$个字符表示给出的字符串。
输出格式:
一行一个整数,表示不一样的子串个数。
题解:
知识点:
后缀数组,LCP
分析:
其实求本质不同的子串的个数这类问题,很容易联想到后缀数据结构。其实可以发现子串不同相当于所有后缀的前缀不同的情况,所以我们把问题的统计变成了统计前缀的不同个数。
我们以$sa[1],sa[2],sa[3],sa[i] \cdots,sa[n]$的顺序统计每个$suffix$,可以发现每次加入的后缀的前缀的个数为$n-sa[i]+1$,但是这里面有很多是重复的,我们要把它们减掉,又$height[i]$的定义我们可以知道,既然前$i-1$处已经计算过$suffix(sa[i])的前height[i]$位了,那么我们把$height[i]$减掉就是答案了,这样就可以线性地解决问题。
时间复杂度:$O(n\log_{2}n)$
代码:
1 |
|
现在我们考虑变成多组数据,在时间复杂度允许的情况下,直接搞就好了,但是注意字符集大小每次要恢复到128,数组要清空。(Eg.SPOJ694 705)
而LZOJ里面的那道把数据组数开到了$10^{3}$,但是同时字符集变小了,这样也是可以跑过去的(常数不能太大)。