字符串匹配之KMP—全力解析

字符串匹配之KMP—全力解析

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

近日,一同学面试被问到字符串匹配算法,结果因为他使用了暴力法,直接就跪了(如今想想这种面试官真的是不合格的,陈皓的一篇文章说的非常好,点击阅读)。字符串匹配方法大概有:BF(暴力破解法), 简化版的BM,KMP,BM,普通情况下,大家听说最多的应该就是KMP算法了。之前学习过,因为时间间隔比較大,记不太清楚了,今天上网查了下,发现写KMP的文章是不少,可是真正清楚简洁就没有了(july的文章太繁琐),所以自己就研究了一晚上,弄清楚了kmp的计算过程,也就在此分享下。

1. 假设你如今全然不知道KMP是个神马玩意,请先阅读 阮一峰《字符串匹配的KMP算法》

KMP算法最难理解的是就是next数组的计算过程,在此分享下我所理解的kmp算法以及next数组的计算过程(假设看前面理论比較头大,能够先看后面样例的计算过程,在回过头来看理论就会释怀):

     1. next数组的计算过程: 
          申明:next数组下标从0算起, 定义next[0]=-1, next[1]=0; 模式串记为T[ ]
          假如求 T中 j+1 位的next[j+1]:
          将其 前一位(模式字符)的内容与其前一位的next值(next[j])的内容(T[next[j]])进行比較:
               假设它们相等(T[j]==T[next[j]]),则next[j+1] = next[j]+1;
               假设他们不相等,则继续向前寻找,直到找到next值相应的内容与前一位相等为止,则在这个next值上加一;
               假设直到第一位都没有与之相等,则next[j+1] = 0;           
           例: 有模式串 “abaababc”
          j=0时,next[0] = -1 ; j=1时,next[1] = 0;
          j=2时,t1!=t0, k=next[0]=-1, next[2]=0;
          j=3时,t2==t0, next[3] = next[2]+1 = 1;
          j=4时,k=next[3]=1, t3!=T[1], k=next[1]=0, T[3]==T[0], next[4]=next[1]+1 = 1;
          j=5时,k=next[4]=1, T[4]==T[1], next[5]=next[4]+1=2;
          j=6时,k=next[5]=2, T[5]==T[2], next[6]=next[5]+1=3;
          j=7时,k=next[6]=3, T[6]!=T[3], k=next[3]=1, T[6]==T[1], next[7]=next[3]+1 = 2;



字符串匹配之KMP---全力解析

      

     2. 上述算法的实现:
     
       //update 2014-04-19 10:08
       void calNext(const char *T, int *next){
          int n = strlen(T);
          if(n<=0) return ;
          next[0] = -1;
          next[1] = 0;
          int j=0, k=-1;
          while(j<n){
               if(k==-1 || T[j]==T[k]){
                    ++j;
                    ++k;
                    next[j] = k;
               }
               else  k = next[k];
          }
     }
     3. KMP主算法:
          设置比較起始下标: i=0, j=0;
          循环直到 i+m>n 或者 T中全部字符都以比較完成
               a. 假设 S[i]==T[j], 则继续比較S和T的下一个字符; 否则
               b. 将 j=next[j], 从这位置開始继续进行比較;
               c. 假设j==-1, 则将 i 和 j 分别加1, 继续比較;
          假设T中全部字符均比較完成,则返回匹配的起始下标,否则返回-1;
     4. KMP算法实现:

     
       //update 2014-04-19 10:08
       int kmpmatch(const char *S, const char *T){
          if(S==NULL || T==NULL) return -1;
          int n = strlen(S);
          int m = strlen(T);
          int next[m];
          calNext(T, next);
          int i=0, j=0;
          while(i+m<=n){
               for( ; j<m&&i<n&&S[i]==T[j]; ++i, ++j) ;
               if(j==m) return i-m;
               j = next[j];
               if(j==-1){
                    ++i;
                    ++j;
               }
          }
          return -1;
     }
举例: 设主串 S=”ababcabcacbab”, 模式 T=”abcac”
          依照上述方法计算得next[]={-1,0,0,0,1}


字符串匹配之KMP---全力解析



字符串匹配之KMP---全力解析


本篇文章主要关注next数组的计算及kmp主算法的实现。
要了解next数组是什么?
为什么要这么计算next数组?
參见下一篇文章(字符串匹配之KMP算法(续)—还原next数组 )

.

假设你认为本篇对你有收获,请帮顶。

另外,我本人开通了微信公众号–分享技术之美,我会不定期的分享一些我学习的东西.
你能够搜索公众号:
swalge
 或者扫描下方二维码关注我
字符串匹配之KMP---全力解析

(转载文章请注明出处: http://blog.csdn.net/swagle/article/details/23969683 )

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/118913.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Java继承的概念及方法

    Java继承的概念及方法继承的概念继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。生活中的继承:兔子和羊属于食草动物类,狮子和豹属于食肉动物类。食草动物和食肉动物又是属于动物类。所以继承需要符合的关系是:

    2022年7月8日
    25
  • 补码运算加减乘除原理是什么_计算机组成原理补码乘法运算

    补码运算加减乘除原理是什么_计算机组成原理补码乘法运算首先我们来看为什么要使用补码运算法:         因为人脑可以知道第一位是符号位,在计算的时候我们会根据符号位,选择对真值区域的加减.(真值的概念在本文最开头).但是对于计算机,加减乘数已经是最基础的运算,要设计的尽量简单.计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂!于是人们想出了将符号位也参与运算的方法.我们知道,根据运算法则减去一个正数等于加上一个负数…

    2022年9月15日
    3
  • acwing-257. 关押罪犯(二分图+二分)「建议收藏」

    acwing-257. 关押罪犯(二分图+二分)「建议收藏」S 城现有两座监狱,一共关押着 N 名罪犯,编号分别为 1∼N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为 c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为 c 的冲突事件。每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到 S 城 Z 市长那里。公务繁忙的 Z 市长只会去看

    2022年8月9日
    7
  • 操作系统进程有若干个状态,若一个进程_进程和线程的概念

    操作系统进程有若干个状态,若一个进程_进程和线程的概念第二章进程管理-进程、线程进程的概念进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。(线程是调度的基本单位)程序:是静态的,是一个存放在磁盘里的可执行文件,是一系列指令的集合进程:是动态的,是程序的一次执行过程

    2025年8月28日
    5
  • Otsu‘s Thresholding的工作原理「建议收藏」

    Otsu‘s Thresholding的工作原理「建议收藏」Otsu’sThresholding的工作原理

    2022年5月22日
    34
  • Wireshark使用教程

    Wireshark使用教程文章目录安装使用开始捕获以wireshark2.6.3汉化版为例安装除了路径是自定义之外,其它均默认即可。使用开始捕获菜单“捕获-选项”,设置需要捕获的网络适配器,点击“开始”。也可以在菜单“捕获-开始”、“捕获-结束”来控制开始结束。在“捕获-捕获过滤器”编辑捕获表达式在上述“捕获”菜单中进行的操作,也可以在工具栏进行,如下图捕获结果着色规则在菜单“视图-着色规则”…

    2022年6月16日
    32

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号