KMP(模板)

算法讲解: KMP算法最浅显易懂
模板来源: 从头到尾彻底理解KMP

首先:KMP的模板为:

void get_next(char *a, int *nex) {
    nex[1] = 0;
    for (int i = 2, j = 0; i <= len; i++) {
        while (j > 0 && a[i] != a[j + 1])j = nex[j];
        if (a[i] == a[j + 1])j++;
        nex[i] = j;
    }
    return;
}

int KMP(char *a, char *b) {//b为母串
    for (int i = 1, j = 0; i <= strlen(b + 1); i++) {
        while (j > 0 && (j == strlen(a + 1) || b[i] != a[j + 1]))j = nex[j];
        if (b[i] == a[j + 1])j++;
        f[i] = j;
        //若a在b中出现,,返回出现的位置
        //if(f[i]==strlen(a+1)){return i-strlen(a);}
    }
    return 1;
}

例题:2018 UESTC Training for Search Algorithm & String——L主楼

题意:求字符串中的最短循环节,并输出该循环节

KMP最小循环节、循环周期:
定理:假设S的长度为len,则S存在最小循环节,循环节的长度L为len-next[len],子串为S[0…len-next[len]-1]。
(1)如果len可以被len - next[len]整除,则表明字符串S可以完全由循环节循环组成,循环周期T=len/L。
(2)如果不能,说明还需要再添加几个字母才能补全。需要补的个数是循环个数L-len%L=L-(len-L)%L=L-next[len]%L,L=len-next[len]。

注意这里的len是原字符串的len+1;

 1 #include<cstdio>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 int T, len;
 6 char s[100000 + 5];
 7 int nex[100000 + 5];
 8 
 9 void get_next(char* p, int next[]){
10     int pLen = strlen(p) + 1;//要求循环节长度时这里才+1
11     next[0] = -1;
12     int k = -1;
13     int j = 0;
14     while (j < pLen - 1){  
15         if (k == -1 || p[j] == p[k]){
16             ++j;++k;
17             if (p[j] != p[k])
18                 next[j] = k;
19             else
20                 next[j] = next[k];
21         }
22         else{
23             k = next[k];
24         }
25     }
26 }
27 
28 int kmp(char* s, char* p){
29     int i = 0;
30     int j = 0;
31     int sLen = strlen(s);
32     int pLen = strlen(p);
33     while (i < sLen && j < pLen){
34             //①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++      
35         if (j == -1 || s[i] == p[j]){
36             i++;
37             j++;
38         }
39         else{
40             //②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]      
41             //next[j]即为j所对应的next值        
42             j = nex[j];
43         }
44     }
45     if (j == pLen)
46         return i - j;
47     else
48         return -1;
49 }
50 
51 int main() {
52     scanf("%d", &T);
53     while (T--) {
54         memset(nex, 0, sizeof(nex));
55         scanf("%d", &len);
56         scanf("%s", s);
57         len = strlen(s);
58         get_next(s, nex);
59         printf("%d
", len - nex[len]);
60         for (int i = 0; i < len - nex[len]; i++)
61             printf("%c", s[i]);
62         printf("
");
63     }
64     return 0;
65 }

HDU1711(数字KMP)

 1 #include<cstdio>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 int T, len;
 6 int len1, len2;
 7 int s1[1000000 + 5];
 8 int s2[1000000 + 5];
 9 int nex[1000000 + 5];
10 
11 void get_next(int* p, int next[]) {
12     int pLen = len2;//要求循环节长度时这里才+1
13     next[0] = -1;
14     int k = -1;
15     int j = 0;
16     while (j < pLen - 1) {
17         if (k == -1 || p[j] == p[k]) {
18             ++j; ++k;
19             if (p[j] != p[k])
20                 next[j] = k;
21             else
22                 next[j] = next[k];
23         }
24         else {
25             k = next[k];
26         }
27     }
28 }
29 
30 int kmp(int* s, int* p) {
31     int i = 0;
32     int j = 0;
33     int sLen = len1;
34     int pLen = len2;
35     get_next(s2, nex);
36     while (i < sLen && j < pLen) {
37         //①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++      
38         if (j == -1 || s[i] == p[j]) {
39             i++;
40             j++;
41         }
42         else {
43             //②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]      
44             //next[j]即为j所对应的next值        
45             j = nex[j];
46         }
47     }
48     if (j == pLen)
49         return i - j;
50     else
51         return -1;
52 }
53 
54 int main() {
55     scanf("%d", &T);
56     while (T--) {
57         scanf("%d %d", &len1, &len2);
58         for (int i = 0; i < len1; i++)
59             scanf("%d", &s1[i]);
60         for (int i = 0; i < len2; i++)
61             scanf("%d", &s2[i]);
62         if (kmp(s1,s2) == -1)
63             printf("-1
");
64         else
65             printf("%d
", kmp(s1,s2)+1);
66     }
67     return 0;
68 }
原文地址:https://www.cnblogs.com/romaLzhih/p/9489822.html