KMP算法,是处理字符串模式匹配问题的。能够在线性时间判断模式串在主串中出现的次数(如果根本不是子串,输出0)。
这个时候我要再安利一手Hash。Hash也能在线性时间解决!!!!(众人:你不是要说KMP吗)啊对,让我们来看看今天的主角。KMP算法的核心,就是其next数组,这个next数组往往可以解决许多问题。
现给出定义:next[i]表示模式串(短的内个)中以i结尾的非前缀子串与A的前缀能匹配上的最大长度。
即:next[i] = max{j},且j要满足j < i且str[i - j + 1~i] = str[1~j]。
这是怎么想出来的呢.......先看匹配的常规方法,一位一位匹配,假设匹配到某一位就不对了,常规来说是O(n²)的处理,退两个指针再匹配。但我们想充分利用已匹配那一段的特点。如果前面已经匹配成功的一段里,有和前缀相同的,我们才有继续匹配这段的价值。
就比如说,两个串:
xxxxxxyyyyyyyy
xxxxyyyy
这个时候由于前面有相似的,我们可以直接只挪动模式串指针,从如下开始匹配:
xxxxxxyyyyyyyy
xxxxyyyy
发现还不行,怎么办呢?所以我们再错后,就得到了答案。
next数组正是O(1)的为我们提供了每次移动后的位置。
对两串匹配可以得到数组f,f[i]表示主串中以i结尾的子串与A的前缀能匹配的最长长度。二者求法十分相似。
贴一个李煜东前辈模板吧:
next[1] = 0;
for(int i = 2, j = 0; i <= n; ++i) {
while(j > 0 && str[i] != str[j + 1]) j = next[j];
if(str[i] == str[j + 1]) j++;
next[i] = j;
}
for(int i = 1, j = 0; i <= m; ++i) {
while(j > 0 && (j == n || str1[i] != str[j + 1])) j = next[j];
if(str1[i] == str[j + 1]) j++;
f[i] = j;
//if(f[i] == n),则是模式串在主串中的一次出现
}
就介绍到这吧。