KMP模板

首先推荐一下B站上一个阿三哥讲的KMP,通俗易懂,深入浅出就是英语口语有些别扭

传送门:汪都能听懂的KMP字符串匹配算法【双语字幕】

(时间有限,有机会把配图补上)

 

匹配原理:

kmp算法是一种模式匹配算法,时间复杂度为O(m+n)。

kmp最大的特点是,当在某个字符匹配不成功时,不需要从头开始,利用模式串的前缀和后缀来进行优化,若存在相同的前缀和后缀,则只需要在相同的前缀之后继续匹配即可。难点在于相同的前缀和后缀如何得到,即next数组如何得到。

next数组:

两个下标指针i,j,初始j=0,i=1,比较a[i]和a[j],如果相同,两个下标同时向后移,如果不相同,则j = next[j-1],继续比较。时间复杂度O(n),空间复杂度O(n)。

利用next数组匹配:

进行模式匹配时,如果匹配失败,则模式串下标移动到next[i-1]的值的位置,继续匹配。时间复杂度O(m)。

直接上模板:

next数组计算:

 

 1 void getnext()
 2 {
 3     next[0] = 0; // 第一个元素初始化为0
 4     int i,j;
 5     for(i=1,j=0; i < n2; )
 6     {
 7         if(pattern[i] == pattern[j]) { // 如果相等,计算next数组,然后同时后移
 8             next[i] = next[i-1]+1;
 9             j++; i++;
10         } else {
11             if(j != 0) // 不相等,判断是否为0
12             {
13                 j = next[j-1]; // 移动
14             } else next[i++] = 0;
15         }
16     }
17 }

 

kmp算法实现:

 

 1 int kmp()
 2 {
 3     int i,j;
 4     for(i=0,j=0; i < n1 && j < n2; )
 5     {
 6         if(j == n2) break;  // 匹配结束,跳出循环
 7         if(str[i] == pattern[j]) // 匹配成功,同时后移
 8         {
 9             i++;
10             j++;
11         } else {
12             if(j != 0) j = next[j-1]; // 匹配失败,若j不为0,移动
13             else i++; // j为零,i移动
14         }
15     }
16     if(j == n2) return i-j; // 返回主串中的下标
17     else return -1; // 匹配失败,返回异常
18 }

 

 

 

完整测试代码:

 

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 char str[100];
 5 char pattern[100];
 6 int next[100];
 7 int n1,n2;
 8 void getnext()
 9 {
10     next[0] = 0; // 第一个元素初始化为0
11     int i,j;
12     for(i=1,j=0; i < n2; )
13     {
14         if(pattern[i] == pattern[j]) { // 如果相等,计算next数组,然后同时后移
15             next[i] = next[i-1]+1;
16             j++; i++;
17         } else {
18             if(j != 0) // 不相等,判断是否为0
19             {
20                 j = next[j-1]; // 移动
21             } else next[i++] = 0;
22         }
23     }
24 }
25 int kmp()
26 {
27     int i,j;
28     for(i=0,j=0; i < n1 && j < n2; )
29     {
30         if(j == n2) break;  // 匹配结束,跳出循环
31         if(str[i] == pattern[j]) // 匹配成功,同时后移
32         {
33             i++;
34             j++;
35         } else {
36             if(j != 0) j = next[j-1]; // 匹配失败,若j不为0,移动
37             else i++; // j为零,i移动
38         }
39     }
40     if(j == n2) return i-j; // 返回主串中的下标
41     else return -1; // 匹配失败,返回异常
42 }
43 int main()
44 {
45     cin >> str >> pattern;
46     n1 = strlen(str);
47     n2 = strlen(pattern);
48     getnext();
49     cout << kmp();
50     return 0;
51 }
View Code

 

posted @ 2020-08-05 12:37  不敢说的梦  阅读(700)  评论(0)    收藏  举报