KMP算法就是在朴素(BF)算法增加滑动窗口
朴素算法:
int NaiveMatching(string T, string P, int start) //**未增加特征向量(滑动窗口)**
{
int j = 0;
int i = start;
int pLen = P.length();
int tLen = T.length();
if (tLen - start < pLen) return -1; // **目标比模式短**
while (j < pLen && i < tLen) {
if (P[j] == T[i]) {
i++;
j++;
}
else {
i = i - j + 1;
j = 0;
}
}
if (j >= pLen) return i - pLen;
else return -1;
}
KMP算法:增加特征向量
int KMPStrMatching(string T, string P, int* N, int start) //**增加特征向量(滑动窗口)**
{
int j = 0;
int i = start;
int pLen = P.length();
int tLen = T.length();
if (tLen - start < pLen) return -1; // 目标比模式短
while (j < pLen && i < tLen) {
if (P[j] == T[i]) {
i++;
j++;
}
else {
i = i - j + j - N[j]; // 特征向量移动 已匹配字符 - 特征向量表中的值 让i进行滑动
j = 0;
}
}
if (j >= pLen) return i - pLen;
else return -1;
}
特征向量(滑动窗口)
int* findNext(string P)
{
int j, k;
int m = P.length();
assert(m > 0);
int* next = new int[m];
assert(next != 0);
next[0] = -1;
j = 0; //子串B
k = -1; // 子串A
while (j < m - 1) {
while (k >= 0 && P[k] != P[j]) {
k = next[k];
//子串A和子串B下一位不相等
//这个时候子串A中进行自我求最大公开的k
// 匹配子串A最大前后缀 就是next[k-1]
//因为下面已经k++所以是next[k]
}
j++;
k++;
next[j] = k;
//如果子串A和子串B下一位相等
// next[j] = next[j-1]+1 即等于k
]
//cout<<next[j]<<endl;
}
//next[j + 1] = -2;
return next;
}
优化:
int* findNext_U(string P)
{
int j, k;
int m = P.length();
assert(m > 0);
int* next = new int[m];
assert(next != 0);
next[0] = -1;
j = 0;
k = -1;
while (j < m - 1) {
while (k >= 0 && P[k] != P[j]) {
k = next[k];
}
j++;
k++;
if (P[k] == P[j]) {
//因为子串A和子串B相等
//即下次子串A匹配到子串B位置时候必然是不符合的
//那么就可以跳过,特征值减少 意味着滑动窗口增大
next[j] = next[k];
}
else {
next[j] = k;
}
}
return next;
}