zoukankan      html  css  js  c++  java
  • kmp-模板-hd-1711

    p数组记录的是当该位置上失配的时候,跳到第几个进行继续匹配;
     1 /*
     2    题意:给两个数串,求模板串第一此出现在源串中的位置,开头的位置;没有输出-1;
     3    算法:kmp
     4    先对字符串进行自匹配;
     5    然后串间匹配;
     6  */
     7 #include<iostream>
     8 #include<cstdio>
     9 #include<cstring>
    10 #include<string>
    11 using namespace std;
    12 int s[1000005],t[10005],p[10005];//s是源串,t是模板串,p是自匹配数组(next);
    13 int n,m;
    14 int kmp()//模板;
    15 {
    16     int ans=0;
    17     p[0]=p[1]=0;
    18     //p数组是错位排列的,p[i]表示的是p[i-1]的信息;即到目前为止的最长前缀;
    19     for(int i=1;i<m;i++)
    20     {
    21         int j=p[i];
    22         while(j&&t[i]!=t[j])
    23         {
    24             j=p[j];//定位j的位置;
    25         }
    26         p[i+1]=t[i]==t[j]?j+1:0;
    27     }
    28     int j=0,temp=0;
    29     for(int i=0;i<n;i++)
    30     {
    31         while(j&&s[i]!=t[j])
    32         {
    33             j=p[j];
    34         }
    35         if(s[i]==t[j])
    36             j++;
    37         if(j==m)
    38             return i+1-m+1;
    39     }
    40     return 0;
    41     //可以判断是否有子串,也可以计算有多少子串;
    42 }
    43 int main()
    44 {
    45     int T;
    46     scanf("%d",&T);
    47     while(T--)
    48     {
    49         memset(s,0,sizeof(s));
    50         memset(t,0,sizeof(t));
    51         scanf("%d%d",&n,&m);
    52         for(int i=0;i<n;i++)
    53             scanf("%d",&s[i]);
    54         for(int i=0;i<m;i++)
    55         {
    56             scanf("%d",&t[i]);
    57         }
    58         int ans=kmp();
    59         if(ans==0)
    60             printf("-1
    ");
    61         else
    62             printf("%d
    ",ans);
    63     }
    64     return 0;
    65 }
    View Code

     下面是自己按照俞勇的书敲的模板;比较详细一点,理解更深了一点;

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 using namespace std;
     6 string s,pattern;
     7 int next[10100]={0};
     8 int n,m;
     9 int position[100000]={0};//标记每一个字串的起始位置;
    10 void kmp()
    11 {
    12     for(int i=1;i<n;i++)
    13     {
    14         int j=i;
    15         while(j>0)
    16         {
    17             j=next[j];
    18             if(pattern[j]==pattern[i])
    19             {
    20                 next[i+1]=j+1;
    21                 break;
    22             }
    23         }
    24     }
    25     for(int i=0,j=0;i<m;i++)
    26     {
    27         //i标记的是大串上的位置,j标记的是小串上的位置;
    28         if(j<n&&s[i]==pattern[j])
    29             j++;
    30         else
    31         {
    32         //    如果失配j就跳到小串的下一个位置继续匹配;
    33             while(j>0)//j等于0就是没有继续可跳的位置;
    34             {
    35                 j=next[j];
    36                 if(s[i]==pattern[j])
    37                 {
    38                     j++;
    39                     break;
    40                 }
    41             }
    42         }
    43         if(j==n)
    44             cout<<i-n+1+1<<endl;//返回起始位置(i-n+1)是数组中的位置,再加1是从一开始的位置定位;
    45     }
    46     //没有子串,在这里可以返回-1;
    47 }
    48 int main()
    49 {
    50     cin>>s>>pattern;
    51     n=pattern.size();
    52     m=s.size();
    53     kmp();
    54     return 0;
    55 }
    View Code
  • 相关阅读:
    phpHttp请求头
    第八周学习总结
    梦断代码阅读笔记-03
    第七周学习总结
    针对自己开发项目的NABC的认知
    梦断代码阅读笔记
    第六周学习总结
    第五周学习总结
    移动端疫情展示
    第四周学习总结
  • 原文地址:https://www.cnblogs.com/by-1075324834/p/4514633.html
Copyright © 2011-2022 走看看