• KMP模板


    参考:https://blog.csdn.net/qq_30241305/article/details/50700199

    A.更正后模板代码,求子串最初出现位置

     1 #include <iostream>
     2 #include  <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 int nexta[10005],a[1000005],s[10005];
     6 int n,m;
     7 void getnexta(int s[])//初始next数组
     8 {
     9     memset(nexta,0,sizeof(nexta));
    10     int k = -1,j = 0;
    11     nexta[0] = -1;
    12 
    13     while(j <m)//这里的m为全局变量,为模式串长度
    14     {
    15 
    16         if(k == -1 || s[k] == s[j])
    17         {
    18             nexta[j + 1] = k + 1;
    19             j ++;
    20             k ++;
    21         }
    22         else
    23         {
    24             k = nexta[k];
    25         }
    26     }
    27 
    28 }
    29 int kmp(int s[],int t[])//t模式串,s母串
    30 {
    31     getnexta(t);
    32 
    33     int i = 0,j = 0;
    34     while(i < n && j < m)
    35     {
    36         if(j == -1 || s[i] == t[j])
    37         {
    38             i ++;
    39             j ++;
    40         }
    41         else
    42         {
    43             j = nexta[j];
    44         }
    45         if(j == m)
    46         {
    47             return i - j+ 1;//匹配开始位置
    48         }
    49     }
    50     return -1;
    51 }
    52 int main()
    53 {
    54 //    freopen("in.txt","r",stdin);
    55     int T;
    56     scanf("%d",&T);
    57     while(T--)
    58     {
    59         scanf("%d%d",&n,&m);
    60         for(int i = 0;i < n; i ++)
    61         {
    62             scanf("%d",&a[i]);
    63         }
    64         for(int j = 0; j < m;j ++)
    65         {
    66             scanf("%d",&s[j]);
    67         }
    68         printf("%d
    ",kmp(a,s));
    69     }
    70     return 0;
    71 }

    B.较好的模板,求字串出现次数,可重叠

     1 #include <iostream>
     2 #include  <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 int nexta[1000006];
     6 char t[1000006],s[1000006];
     7 void getnexta(char s[])
     8 {
     9     memset(nexta,0,sizeof(nexta));
    10     int n = strlen(s);//这里的s并非为母串,而要看传入的数组!
    11     int k = -1,j = 0;
    12     nexta[0] = -1;
    13     while(j <n)
    14     {
    15 
    16         if(k == -1 || s[k] == s[j])
    17         {
    18             nexta[j + 1] = k + 1;
    19             j ++;
    20             k ++;
    21         }
    22         else
    23         {
    24             k = nexta[k];
    25         }
    26     }
    27 
    28 }
    29 int kmp(char s[],char t[])//t模式串,s母串.
    30 {
    31     getnexta(t);
    32     int ans = 0;
    33     int n = strlen(s),m = strlen(t);
    34     int i = 0,j = 0;
    35     while(i < n && j < m)
    36     {
    37         if(j == -1 || s[i] == t[j])
    38         {
    39             i ++;
    40             j ++;
    41         }
    42         else
    43         {
    44             j = nexta[j];
    45         }
    46         if(j == m)//根据题目要求改变
    47         {
    48             ans ++;
    49             j = nexta[j];
    50         }
    51     }
    52     return ans;
    53 }
    54 int main()
    55 {
    56    // freopen("in.txt","r",stdin);
    57     int T;
    58     scanf("%d",&T);
    59     while(T--)
    60     {
    61         scanf("%s%s",t,s);
    62         printf("%d
    ",kmp(s,t));
    63     }
    64     return 0;
    65 }

     C。不能重叠

     1 #include <iostream>
     2 #include  <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 int nexta[1006];
     6 char t[1006],s[1006];
     7 void getnexta(char s[])
     8 {
     9     memset(nexta,0,sizeof(nexta));
    10     int n = strlen(s);
    11     int k = -1,j = 0;
    12     nexta[0] = -1;
    13     while(j < n )
    14     {
    15 
    16         if(k == -1 || s[k] == s[j])
    17         {
    18             nexta[j + 1] = k + 1;
    19             j ++;
    20             k ++;
    21         }
    22         else
    23         {
    24             k = nexta[k];
    25         }
    26     }
    27 
    28 }
    29 int kmp(char s[],char t[])//t模式串,s母串.
    30 {
    31     getnexta(t);
    32     int ans = 0;
    33     int n = strlen(s),m = strlen(t);
    34     int i = 0,j = 0;
    35     while(i < n && j < m)
    36     {
    37         if(j == -1 || s[i] == t[j])
    38         {
    39             i ++;
    40             j ++;
    41         }
    42         else
    43         {
    44             j = nexta[j];
    45         }
    46         if(j == m)//根据题目要求改变
    47         {
    48             ans ++;
    49             j = 0;
    50         }
    51     }
    52     return ans;
    53 }
    54 int main()
    55 {
    56    // freopen("in.txt","r",stdin);
    57     while(1)
    58     {
    59         scanf("%s",s);
    60         if(strcmp(s,"#") == 0)
    61             break;
    62         scanf("%s",t);
    63         printf("%d
    ",kmp(s,t));
    64     }
    65     return 0;
    66 }

     D。最小循环节

     1 #include <iostream>
     2 #include  <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 int nexta[100005];
     6 char s[100005];
     7 void getnexta(char s[])
     8 {
     9     memset(nexta,0,sizeof(nexta));
    10     int n = strlen(s);
    11     int k = -1,j = 0;
    12     nexta[0] = -1;
    13     while(j < n )
    14     {
    15         if(k == -1 || s[k] == s[j])
    16         {
    17             nexta[j + 1] = k + 1;
    18             j ++;
    19             k ++;
    20         }
    21         else
    22         {
    23             k = nexta[k];
    24         }
    25     }
    26 }
    27 int main()
    28 {
    29    // freopen("in.txt","r",stdin);
    30    int T,ans,n,temp;
    31    scanf("%d",&T);
    32     while(T --)
    33     {
    34         scanf("%s",s);
    35         n = strlen(s);
    36         getnexta(s);
    37         temp = n - nexta[n];//最小循环节,例如s:abcdeabc,则串长n为8,nexta[n]为s[0]到s[7]的
    38         if(temp == n)//前,后缀匹配长度为3(abc),所以n-next[n]为8-3=5,即最小循环节长(abcde)
    39         {
    40             ans = n;//除nexta[0]为-1外,其余nexta值最小为0,此情况为整体字符串为一个循环节
    41         }
    42         else if(n % temp == 0)//自身已经循环
    43         {
    44             ans = 0;
    45         }
    46         else
    47         {
    48             ans = temp - (n % temp);
    49         }
    50         printf("%d
    ",ans);
    51     }
    52     return 0;
    53 }

     G.

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 int nexta[1000002];
     6 char s[1000002];
     7 int n;
     8 void getnexta()
     9 {
    10     memset(nexta,0,sizeof(nexta));
    11     int k = -1,j = 0;
    12     nexta[0] = -1;
    13     while(j < n )
    14     {
    15 
    16         if(k == -1 || s[k] == s[j])
    17         {
    18             nexta[j + 1] = k + 1;
    19             j ++;
    20             k ++;
    21         }
    22         else
    23         {
    24             k = nexta[k];
    25         }
    26     }
    27 
    28 }
    29 int main()
    30 {
    31     //freopen("in.txt","r",stdin);
    32     int ans;
    33     while(1)
    34     {
    35         ans = 0;
    36         scanf("%s",s);
    37         if(strcmp(s,".") == 0)
    38             break;
    39         n = strlen(s);
    40         getnexta();
    41         if(n % (n - nexta[n])  == 0 )//记住n-nexta[n]为最小循环节长度
    42             ans  = n / (n - nexta[n]);
    43         else
    44             ans = 1;
    45         printf("%d
    ",ans);
    46     }
    47     return 0;
    48 }
    49 
    50 
    51 //ababa

     H。题意:https://blog.csdn.net/alongela/article/details/8196915

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 int nexta[1000002];
     6 char s[1000002];
     7 int ans[1000002];
     8 int n;
     9 void getnexta()
    10 {
    11     memset(nexta,0,sizeof(nexta));
    12     int k = -1,j = 0;
    13     nexta[0] = -1;
    14     while(j < n )
    15     {
    16 
    17         if(k == -1 || s[k] == s[j])
    18         {
    19             nexta[j + 1] = k + 1;
    20             j ++;
    21             k ++;
    22         }
    23         else
    24         {
    25             k = nexta[k];
    26         }
    27     }
    28 
    29 }
    30 
    31 int main()
    32 {
    33     //freopen("in.txt","r",stdin);
    34     int temp,k;
    35     while(scanf("%s",s) != EOF)
    36     {
    37         k = 0;
    38         n = strlen(s);
    39         getnexta();
    40         temp = n;
    41         ans[k] = n;
    42         k ++;
    43         while(nexta[temp]!= 0)//当nexta[temp]==0说明该字符前的串没有相同前后缀
    44         {
    45             temp = nexta[temp];
    46             ans[k] = temp;
    47             k ++;
    48         }
    49         for(int i = k -1; i > 0; i --)
    50             printf("%d ",ans[i]);
    51         printf("%d
    ",ans[0]);
    52 
    53     }
    54     return 0;
    55 }
    56 
    57 
    58 //ababa
  • 相关阅读:
    springboot整合springmvc应用
    spring注解使用
    亨元模式 四大引用 逃逸引用 池化思想
    springboot整合连接池
    springboot整合mybatis(待更新)
    php安装imagick扩展
    js复制功能代码
    PHP7兼容mysql_connect的方法
    linux开机启动
    centos8安装php扩展memcached报错
  • 原文地址:https://www.cnblogs.com/hemeiwolong/p/9503903.html
Copyright © 2020-2023  润新知