- 给定字符串S和子串T。
- 定义n=|s|,m=|T|,extend[i]=S[i~n]与T的最长公公前缀长度。请在线性时间内求出所有的extend。
- 这道题继承上面KMP的思路,我们可以对T的每一个前缀做一次KMP,如果在某个i位置出现,就拿此时前缀长度更新i的extend数组。但是这样复杂度就是O(nm),甚至还不如直接暴力比较求解。
- 考虑一下如何转换思路。字符串算法想要转化成线性的,那我们肯定要尽量避免重复比较。考虑我们怎么通过之前算1~i的extend数组的时候,所做的比较运算能否为此时做贡献呢?假设某一个a的extend我们已经求过了,它的值为L,那么显然S【i~i+L-1】=T【1~L】。此时我们想算extend【K】,已经知道S【K+1~a+L-1】=T【K-a+2~L】。我们想知道能和T的前缀匹配多长,如果我们已经知道了T的后缀和T的前缀匹配的最长长度就好了。为此,我们引入了next数组。
- next i 就是以i为开头的后缀与T匹配的最大长度。那么思路已经比较清晰了。假如我们现在要求K+1的extend,然后我们已知之前extend最大的位置为a,他匹配到了P,next K-a+2=L,那么分两种情况:
- K+L<P,则extend 为L
- K+L>=P ,那么我们已经匹配到了P,P之后的我们不知道,此时暴力枚举就好了。
01-26 19:18