zoukankan      html  css  js  c++  java
  • kmp算法详解

    由于网上题解较多,而他们也讲的非常的好啊,我这里只是简单地再总结一下,以及一些我自己在学习时的感受

    这里先附上我学习时所用的博客,表示我的感谢.

    http://blog.csdn.net/yutianzuijin/article/details/11954939/

    https://segmentfault.com/a/1190000007066358

    http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

    ---------------------------------------------------------------------------------------------------------------------

    一.为什么要用kmp算法

    我们在萌新阶段如果遇到字符串匹配的题目,想必都是最暴力的方法,一位一位的判断,时间复杂度为O(n*m),就像如下图

    很显然我们可以发现第四次和第五次都只判断了第一位就失配了,很明显这两次是很多余的,

    于是kmp算法就依据这个特点来执行

    二.kmp算法中最重要的next数组

    kmp算法作为一个效率很高的字符串匹配方法,next数组便是其中的核心

    他记录的是在第i位时,前缀和后缀都相等时的最大长度

    好吧这样说可能有点抽象,来举个栗子

    字符串 A B C D A B D
    next数组 0 0 0 0 1 2 0

    在第一位{A} 前缀{Ø}  后缀{Ø},next[1]=0;  (Ø表示空集)

    在第二位{AB} 前缀{A}  后缀{B},共同部分{Ø},next[2]=0;

    在第三位{ABC} 前缀{A,AB}  后缀{BC,C},共同部分{Ø},next[3]=0;

    在第四位{ABCD} 前缀{A,AB,ABC}  后缀{BCD,CD,D},共同部分{Ø},next[4]=0;

    在第五位{ABCDA} 前缀{A,AB,ABC,ABCD}  后缀{BCDA,CDA,DA,A},共同部分{A},next[5]=1;

    在第六位{ABCDAB} 前缀{A,AB,ABC,ABCD,ABCDA}  后缀{BCDAB,CDAB,DAB,AB,B},共同部分{AB},next[6]=2;

    在第七位{ABCDABD} 前缀{A,AB,ABC,ABCD,ABCDA,ABCDAB}  后缀{BCDABD,CABD,ABD,BD,D},共同部分{Ø},next[7]=0;

    这就是next的含义,下面我们来讲讲如何求这个值

    1 void pre(){
    2     int k=0;
    3     for (int i=2;i<=len2;++i){
    4         while (k>0&&t[k+1]!=t[i]) k=nxt[k];
    5         if (t[k+1]==t[i]) k++;
    6         nxt[i]=k;
    7     }
    8 }
    View Code

    读者们也可以参照http://www.cnblogs.com/tangzhengyue/p/4315393.html来学习

    三.kmp算法内容

    好吧现在切入正题,前面都是铺垫

    我们前面已经求出了next数组的值了,那么我们应该如何应用呢?

    就像上面的这个字符串匹配,当匹配到了这里,D和上面空格并不匹配

    前面“ABCDAB”是匹配的,那我们就按照下面这个式子

      移动位数 = 已匹配的字符数 - 对应的部分匹配值

      4        = 6        - 2 

    因为还是不能匹配,那我们继续向后移2=2-next[2]位

    因为第一位不能匹配,直接向后移一位

    最后匹配成功,因此我们可以发现,在原字符串中,每个字符都只匹配到了一次,时间复杂度为严格的O(n+m)

    如还是不能理解可学习https://segmentfault.com/a/1190000007066358#articleHeader7

    最后附上kmp部分的代码

    1 void kmp(){
    2     int k=0;
    3     for (int i=1;i<=len1;++i){
    4         while (k>0&&t[k+1]!=s[i]) k=nxt[k];
    5         if (t[k+1]==s[i]) k++;
    6         if (k==len2) printf("%d ",i-len2+1),ans++;
    7     }
    8 }
    View Code

    四.总结

    kmp算法的确是一个效率高,且较好理解的字符串匹配方法,对于解决这方面问题都非常有效

    接下来希望读者也可以完成一些基础题目来巩固

    http://poj.org/problem?id=2406

    http://acm.hdu.edu.cn/showproblem.php?pid=2087

    最后在推荐一个炒鸡强的一个大佬博客 http://www.cnblogs.com/whc200305/p/7580086.html

  • 相关阅读:
    Centos5.8 安装 ImageMagick 6.8.9-3
    Centos5.8 安装 Redmine
    Apache配置中的ProxyPass 和 ProxyPassReverse
    Centos5.8 安装SVN并配置HTTP访问
    Centos5.8 安装 MySQL5.6.19
    Centos5.8 安装 PHP5.5 和 memcached
    CentOS RHEL 安装 Tomcat 7
    Centos5.8 iptables管理
    在SecureCRT中使用rz和sz传输文件
    在Mac mini上安装 ESXi 5.5
  • 原文地址:https://www.cnblogs.com/logic-yzf/p/7529943.html
Copyright © 2011-2022 走看看