KMP算法是改進的字符串匹配算法,時間複雜度爲O(m+n)
#include<bits/stdc++.h>
using namespace std;
static int ne[100];//這個數組中盛放的是匹配字符串的next值
void GetNext(char* a)//這個函數是爲了標記匹配字符串的next值
{
int len = strlen(a), i = 0, j = -1;///先求字符串的長度,便於循環賦值
ne[0] = -1;
while (i < len)
{
if (j == -1 || a[i] == a[j])ne[++i] = ++j;
else j = ne[j];
}
}
//實際上每求一個next值要循環兩遍
void KMP(char* a, char* b)
{
GetNext(b);
int lena = strlen(a), lenb = strlen(b), i = 0, j = 0;
while (i < lena && j < lenb)
{
if (j == -1 || a[i] == b[j])
{
j++;
i++;
}
else j = ne[j];
}
if (j == lenb)cout << "找到了,初始位置在:" << i - j + 1;
else cout << "沒找到";
}
int main(void)
{
char s[100], f[100];
scanf("%s", &s);
scanf("%s", &f);
KMP(s, f);
}
舉例:
假設有如下兩個字符串S T
S:abaabaabbabaaabaabbabaab
T:abaabbabaab
很明顯 下劃線之後是匹配成功的部分
abaabaabbabaa abaabbabaab_________________ abaabbabaab
前置工作:
先計算next數組 next[i]表示0-i的字符串的最長相同前綴後綴的長度-1
-1 -1 0 0 1 -1 0 1 2 3 4
第一趟:
________ i =5
________ ↓
abaab | aabbabaaabaabbabaababaab | babaab
________ ↑
________ j=5
當 i=5,j=5時出現不匹配情況,此時next[j-1]=1
第二趟:
根據第一趟的next[j-1]=1
所以後移T字符串,從T字符串索引爲1的位置繼續匹配,i不變
abaab | aabbabaaabaabbabaab
____ab | aabbabaab
直到
__________________ i =13
__________________ ↓
abaabaabbabaa | abaabbabaab____abaabbabaa | b
__________________ ↑
__________________ j=10
當i=13,j=10時出現不匹配情況,此時next[j-1]=3
第三趟:
根據第二趟的next[j-1]=3
所以後移T字符串,從T字符串索引爲3的位置繼續匹配,i不變
abaabaabbabaa | abaabbabaab
____________abaa | bbabaab
直到
__________________ i =13
__________________ ↓
abaabaabbabaa | abaabbabaab____________abaa | bbabaab
__________________ ↑
__________________ j=4
當i=13,j=4時出現不匹配情況,此時next[j-1]=0
第四趟:
根據第二趟的next[j-1]=0
所以後移T字符串,從T字符串索引爲0的位置繼續匹配,i不變
abaabaabbabaa | abaabbabaab
________________a | baabbabaab
直到
__________________ i =13
__________________ ↓
abaabaabbabaa | abaabbabaab________________a | baabbabaab
__________________ ↑
__________________ j=1
當i=13,j=1時出現不匹配情況,此時next[j-1]=-1
當next[j-1]=-1時,說明已經沒有相同的前後綴了,直接把T串後移一位即可。
abaabaabbabaaabaabbabaab
_________________abaabbabaab
此時匹配成功