• KMP和扩展KMP


    文章网上太多这里提一下代码细节:

    KMP:

     1 scanf("%s
    ",s);
     2 scanf("%s
    ",t);
     3 int ls=strlen(s),lt=strlen(t);
     4 f[0]=f[1]=0;
     5 for(int i=1;i<lt;++i)
     6 {
     7     int j=f[i];
     8     while(j&&t[j]!=t[i]) j=f[j];
     9     if(t[j]==t[i]) f[i+1]=j+1;else f[i+1]=0;
    10 }
    11 int j=0;
    12 for(int i=0;i<ls;++i)
    13 {
    14     while(j&&t[j]!=s[i]) j=f[j];
    15     if(t[j]==s[i]) ++j;
    16     if(j==lt) printf("%d
    ",i-lt+1);
    17 }//Kmp的代码比较简单理解了就不会出错
    View Code

    扩展KMP:

     1     scanf("%s
    ",s);
     2     scanf("%s
    ",t);
     3     int ls=strlen(s),lt=strlen(t);
     4     next[0]=lt;
     5     next[1]=lt-1;//第一个注意点:对自己匹配的时候是要从第1个位置开始暴力,而不是第0个
     6     for(int i=0;i<lt-1;++i)
     7         if(t[i]!=t[i+1])
     8         {
     9             next[1]=i;
    10             break;
    11         }
    12     int k=1;
    13     for(int i=2;i<lt;++i)
    14     {
    15         int p=k+next[k]-1,l=next[i-k];
    16         if(i+l<=p) next[i]=l;
    17         else
    18         {
    19             int j=p-i+1;
    20             if(j<0) j=0;//注意这里不加会爆掉而且很难找出来
    21             while(i+j<lt&&t[i+j]==t[j]) ++j;
    22             next[i]=j;
    23             k=i;
    24         }
    25     }
    26     ex[0]=lt;//两个串匹配则是从第0个位置开始暴力
    27     for(int i=0;i<lt;++i)
    28         if(s[i]!=t[i])
    29         {
    30             ex[0]=i;
    31             break;
    32         }
    33     k=0;
    34     for(int i=1;i<ls;++i)
    35     {
    36         int p=k+ex[k]-1,l=next[i-k];
    37         if(i+l<=p) ex[i]=l;
    38         else
    39         {
    40             int j=p-i+1;
    41             if(j<0) j=0;//同上
    42             while(i+j<ls&&j<lt&&s[i+j]==t[j]) ++j;
    43             ex[i]=j;
    44             k=i;
    45         }
    46     }
    View Code

    这里来手推一下扩展Kmp:

    设p表示S到达的最远点,而p是由k更新到的,故p=k+ex[k]-1

    故s[k..p]==t[0..p-k]

    我们要求的是ex[i],所以要找出s[i]开头的一些关系,又注意到i>k,故s[i..p]==t[i-k..p-k]

    而又想到应该是s[i..p]==t[0..?],因为匹配的是从0开始的,所以就涉及到了t[i-k..?]和t[0..?]的自身匹配,故引进next[i-k]表示t和t自己匹配(与ex[]一样,只不过ex[]保存的是两个字符串的匹配),设其为L,则有t[i-k..i-k+l-1]==t[0..l-1]

    这里考虑:①i-k+l-1<p-k,则说明匹配到的最远的在最远点P之内,故不会涉及到我们不知道的领域,所以肯定ex[i]=l;

         ②i-k+l-1>=p-k,这就说明s[i..p]==t[0..p-i],那么接下来就从s[p+1]和t[p-i+1]开始暴力判断,并维护k和p

  • 相关阅读:
    多线程编程(6) 从 CreateThread 说起[续四]
    多线程编程(7) 从 CreateThread 说起[续五]
    我最喜欢的邮件客户端软件IncrediMail Xe
    [公告]博客园建立了“专家区”
    [新功能]文章档案
    Lucene.Net的语言处理包中Lucene.Net.Analysis.Cn的Bug
    [好消息]博客园与博文视点、第二书店合作推出“读书心得区”
    推荐一篇有关GC的文章
    [小技巧]在NTFS分区中复制文件的同时如何复制权限
    ShartPoin无法创建门户网站的问题
  • 原文地址:https://www.cnblogs.com/wmrv587/p/3563848.html
Copyright © 2020-2023  润新知