zoukankan      html  css  js  c++  java
  • 关于KMP算法的重大发现

    之前写KMP模板的时候,nx[i]代表最大的一个x,使s[1,x-1]是s[1,i-1]的后缀。(方法1)

    然而网上还有另一种方法求nx数组,nx[i]表示最大的一个x,使s[1,x]是s[1,i]的后缀。(方法2)

    两种nx数组在具体匹配的时候方法稍有不同,但都能正确匹配字符串。

    但是在做字符串DP题的时候,发现网上的题解大多是利用第二种nx数组的性质进行状态的转移。

    当时试着写了一下那种nx的求法,但是觉得很别扭,用不惯也记不住。

    不知所措。

    今天看了一下洛谷的KMP模板(P3375)(传送门),发现得求出第二种nx数组......

    这回把第二种求法忘了,也很反感那么写。

    于是立志要找出两种方法的联系。

    很简单嘛:nx2[i]=nx1[i+1]-1

    同时,getnx的时候要走到m+1(m为模式串长),这样nx[m+1]才有值。

    给一个洛谷P3375的代码。

    注意getnx的改动和最后要求输出nx数组的时候是怎么操作的。

     1 #include<cstdio>
     2 #include<cstring>
     3 
     4 char s1[1000005],s2[1000005];
     5 int nx[1000005];
     6 int pos[1000005],cnt;
     7 int n,m;
     8 
     9 void getnx()
    10 {
    11     nx[1]=0;
    12     for(int i=2,j=1;i<=m+1;)
    13     {
    14         nx[i]=j;
    15         while(j&&s2[i]!=s2[j])j=nx[j];
    16         i++,j++;
    17     }
    18 }
    19 
    20 void kmp()
    21 {
    22     for(int i=1,j=1;i<=n;)
    23     {
    24         while(j&&s1[i]!=s2[j])j=nx[j];
    25         if(j==m)
    26         {
    27             pos[++cnt]=i-m+1;
    28             j=nx[j];
    29         }
    30         else i++,j++;
    31     }
    32 }
    33 
    34 int main()
    35 {
    36     scanf("%s",s1+1);
    37     scanf("%s",s2+1);
    38     n=strlen(s1+1);
    39     m=strlen(s2+1);
    40     getnx();
    41     kmp();
    42     for(int i=1;i<=cnt;i++)printf("%d
    ",pos[i]);
    43     for(int i=1;i<=m;i++)printf("%d ",nx[i+1]-1);
    44     return 0;
    45 }
  • 相关阅读:
    C++并发编程实战---阅读笔记
    设计模式---命令模式
    图解HTTP(六)HTTP首部
    HTTP 状态码
    使用VS2012调试Dump文件
    如何设置C++崩溃时生成Dump文件
    boost::asio::io_service类
    boost::asio 同步&异步例子
    boost::bind
    c++并发编程之原子操作的实现原理
  • 原文地址:https://www.cnblogs.com/eternhope/p/9651420.html
Copyright © 2011-2022 走看看