编程语言
首页 > 编程语言> > KMP算法模板

KMP算法模板

作者:互联网

概述

模板出自kuangbin的博客

典型应用:

给你两个字符串,寻找其中一个字符串是否包含另一个字符串,如果包含,返回包含的起始位置。 

(1) 头文件

1 #include <bits/stdc++.h>
2 using namespace std;
3 const int N = 1e5+10;
4 int Next[N];
5 char S[N],T[N];   // S:主串  T:模式串
6 int slen,tlen;

(2) getNext()函数

 1 void getNext()
 2 {
 3     int j,k;
 4     j = 0;  k = -1; Next[0] = -1;
 5     while(j < tlen)
 6     {
 7         if(k == -1 || T[j] == T[k])
 8             Next[++j] = ++k;
 9         else 
10             k = Next[k];
11     }
12 }

(3) 返回模式串T在主串S中首次出现的位置

 1 // 返回模式串T在主串S中首次出现的位置
 2 // 返回的位置是从0开始的
 3 int KMP_Index()
 4 {
 5     int i = 0,j = 0;
 6     getNext();
 7 
 8     while(i < slen && j < tlen)
 9     {
10         if(j == -1 || S[i] == T[j])
11         {
12             i++;    j++;
13         }
14         else 
15             j = Next[j];
16     }
17     if(j == tlen)
18         return i-tlen;
19     else 
20         return -1;
21 }

(4) 返回模式串在主串S中出现的次数

 1 int KMP_Count()
 2 {
 3     int ans = 0;
 4     int i,j = 0;
 5 
 6     if(slen == 1 && tlen == 1)
 7     {
 8         if(S[0] == T[0])
 9             return 1;
10         else 
11             return 0;
12     }
13     getNext();
14     for(i = 0;i < slen;i++)
15     {
16         while(j > 0 && S[i] != T[j])
17             j = Next[j];
18         if(S[i] == T[j])
19             j++;
20         if(j == tlen)
21         {
22             ans++;
23             j = Next[j];
24         }
25     }
26     return ans;
27 }

(5) 全家福

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 /***************KMP***************/
 5 const int N = 1e5+10;
 6 int Next[N];
 7 char S[N],T[N];   // S:主串  T:模式串
 8 int slen,tlen;
 9 
10 void getNext()
11 {
12     int j,k;
13     j = 0;  k = -1; Next[0] = -1;
14     while(j < tlen)
15     {
16         if(k == -1 || T[j] == T[k])
17             Next[++j] = ++k;
18         else 
19             k = Next[k];
20     }
21 }
22 
23 // 返回模式串T在主串S中首次出现的位置
24 // 返回的位置是从0开始的
25 int KMP_Index()
26 {
27     int i = 0,j = 0;
28     getNext();
29 
30     while(i < slen && j < tlen)
31     {
32         if(j == -1 && S[i] == T[j])
33         {
34             i++;    j++;
35         }
36         else 
37             j = Next[j];
38     }
39     if(j == tlen)
40         return i-tlen;
41     else 
42         return -1;
43 }
44 
45 // 返回模式串在主串S中出现的次数
46 int KMP_Count()
47 {
48     int ans = 0;
49     int i,j = 0;
50 
51     if(slen == 1 && tlen == 1)
52     {
53         if(S[0] == T[0])
54             return 1;
55         else 
56             return 0;
57     }
58     getNext();
59     for(i = 0;i < slen;i++)
60     {
61         while(j > 0 && S[i] != T[j])
62             j = Next[j];
63         if(S[i] == T[j])
64             j++;
65         if(j == tlen)
66         {
67             ans++;
68             j = Next[j];
69         }
70     }
71     return ans;
72 }
73 /***************END***************/
74 
75 int main()
76 {
77     int TT;
78     cin >> TT;
79     while(TT--)
80     {
81         cin >> S >> T;
82         slen = strlen(S);
83         tlen = strlen(T);
84         cout << "模式串T在主串中首次出现的位置是: " << KMP_Index() << endl;
85         cout << "模式串T在主串S中出现的次数为: " << KMP_Count() << endl;
86     }
87     return 0;
88 }
View Code

(6) 补充

KMP的优化

 1 void getNext()
 2 {
 3     int j,k;
 4     j = 0,k = -1,Next[0] = -1;
 5     while(j < tlen)
 6     {
 7         if(k == -1 || T[j] == T[k])
 8         {
 9             j++,k++;
10             if(T[j] == T[k])
11                 Next[j] = Next[k];   // 直接走到下一个不相等的地方
12             else 
13                 Next[j] = k;
14         }
15         else 
16             k = Next[k];
17     }
18 }

Next[]数组求循环节
性质:

  • len-next[i]为此字符串的最小循环节(i为字符串的结尾) 
  • 另外如果len%(len-next[i])==0,此字符串的最小周期就为len/(len-next[i])
  • 如果len%(len-next[i]) != 0 则没有循环节???(小声逼逼)

标签:return,int,Next,++,算法,tlen,KMP,else,模板
来源: https://www.cnblogs.com/duny31030/p/14304217.html