kmp算法失配函数的计算
时间: 2023-12-22 14:25:05 浏览: 173
KMP算法中的失配函数(也称为next数组)可以通过动态规划的方式计算得出。具体来说,对于模式串P的每个位置i,失配函数next[i]表示当P[i]与文本串T中的某个字符失配时,下一步应该将模式串P向右移动多少个位置才能继续匹配。
计算next数组的方法是,从模式串P的第二个字符开始,依次计算每个位置的失配函数。具体来说,假设当前计算到位置i,已经知道了next、next、……、next[i-1]的值,现在要计算next[i]。首先将next[i-1]的值赋给j,然后不断向前跳j步,直到找到一个位置k(k<j),使得P[k]等于P[i-1]。此时,可以得到一个长度为j的前缀和一个长度为j的后缀相等,即P~P[j-1]等于P[i-j]~P[i-1]。因此,可以令next[i]=j,并继续计算下一个位置的失配函数。
如果在跳跃过程中找不到一个位置k满足上述条件,则令j=next[j],继续向前跳跃。
最后,如果模式串P的长度为m,则next[m]=0。
相关问题
kmp模失配
### KMP算法中的模式串失配处理
KMP(Knuth-Morris-Pratt)算法是一种高效的字符串匹配算法,其核心在于通过构建部分匹配表(也称为`next`数组或`failure`函数),减少不必要的字符比较次数。当发生模式串失配时,KMP不会简单地回退到下一个位置重新开始匹配,而是利用已有的匹配信息跳过一些不可能匹配的位置。
#### 部分匹配表的作用
部分匹配表记录了模式串中前缀和后缀的最大重合长度。这种特性使得在失配情况下可以快速定位下一次可能的匹配起点,而无需重复检查已经验证过的字符[^1]。
#### 失配处理的具体过程
假设当前正在比较文本串T的第i个字符与模式串P的第j个字符,如果发现两者不相等,则执行如下操作:
1. **查找失败转移**
利用预先计算好的部分匹配表找到新的起始位置k,满足条件 `P[k..j-1]` 是最长的既是前缀又是后缀的子串。
2. **更新指针**
将模式串的指针调整至新位置k继续尝试匹配,即令 `j = next[j-1]`,其中`next[]`表示部分匹配表。
3. **特殊情况**
如果到达模式串的第一个字符仍然无法匹配,则移动文本串指针向前推进一位并重新开始匹配。
以下是实现上述逻辑的一个典型代码片段:
```cpp
void computeLPSArray(const string& pat, int M, vector<int>& lps) {
int len = 0;
lps[0] = 0; // lps[0] is always 0
int i = 1;
while (i < M) {
if (pat[i] == pat[len]) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1];
} else {
lps[i] = 0;
i++;
}
}
}
}
bool KMPSearch(const string& pat, const string& txt) {
int M = pat.size();
int N = txt.size();
vector<int> lps(M);
computeLPSArray(pat, M, lps);
int j = 0; // index for pat[]
for (int i = 0; i < N;) {
if (pat[j] == txt[i]) {
j++; i++;
}
if (j == M) {
return true; // Match found
j = lps[j - 1]; // Prepare for the next match
}
// Mismatch after j matches
else if (i < N && pat[j] != txt[i]) {
if (j != 0)
j = lps[j - 1];
else
i++;
}
}
return false;
}
```
此代码展示了如何基于部分匹配表来高效处理失配情况,并恢复到一个新的候选位置进行进一步匹配。
KMP算法中失败函数代码
KMP(Knuth-Pratt)算法是一种用于字符串匹配的高效算法,它通过预处理模式串来避免回溯搜索。其中的关键部分是构建“失败函数”(也称为失配函数),这个函数存储了在匹配过程中当前字符不匹配时,模式串允许模式向右移动的最大距离。
失败函数的代码通常会创建一个大小等于模式串长度的数组,名为`failure[]`或`lps[]`(最长公共前后缀)。下面是计算失败函数的基本步骤:
1. 初始化`failure[0] = 0`,因为第一个字符不会有前一个匹配的字符。
2. 遍历模式串从第二个字符开始:
- 如果当前字符 `pattern[i]` 等于前一个字符 `pattern[failure[i-1] + 1`。
- 否则,尝试找到一个更大的前缀 `prefix`,使得 `pattern[failure[prefix]-1:] == pattern[i-failure[prefix]:i]`。如果没有这样的`prefix`,将`failure[i]`设置为0,表示当前位置无法直接跳过,需要从头开始比较。
以下是计算失败函数的伪代码示例:
```python
function compute_failure(pattern):
n = length(pattern)
failure = [0] * (n+1) # Initialize failure array
i = 1 # Current index in pattern
j = failure[0]
while i < n:
if pattern[i] == pattern[j]:
failure[i] = j + 1
i += 1
j += 1
else:
if j != 0: # If not at the beginning
j = failure[j-1]
else: # First mismatch, no previous match available
failure[i] = 0
i += 1
return failure
```
阅读全文
相关推荐

















