算法_00_KMP

来源:互联网 发布:双色球选号过滤软件 编辑:程序博客网 时间:2024/06/06 13:21

问题描述
给定两个字符串str1和 str2,问,str1中是否包含 str2。
如果包含,请返回 str1中 str2开始的位置;
不包含,返回-1.

思路
假设 str1长度为N,str2长度为 M

  1. 笨办法
    从str1的0位置,拿 str2字符串的每个字符依次去匹配。
    时间复杂度:O(N*M),与 str1和 str2的长度都有关。

  2. KMP 算法
    可以将时间复杂度降为 O(N).

首先针对 str2字符串,求它的最大前缀后缀匹配长度数组next[]

  • 构造与 str2长度相等的数组 next[],默认 next[0]=-1; next[1]=0,对于其他位置,next[i]=cn
  • 举例:str2=”abcabcd”, 位置4的 next[4]=1,位置6的next[6]=3,(最大前缀后缀匹配为”abc”,长度为3),next[]={-1,0,0,0,1,2,3}

然后,开始匹配 str1和 str2, i1和 i2分别表示 str1和 str2目前匹配的位置

  • 如果str1[i1]==str2[i2],那么 i1++,i2++
  • 否则,
    • 如果,next[i2]==-1,表示str2在初始位置,一个都还没匹配上,那么,直接将 i1++,从str1下一个位置开始匹配
    • 否则,i2 = next[i2],表示,将 str2往后推(str1的位置 i1是不会往后的,要么不动,要么增加),推到 从next[i2]的位置开始比较。因为从 next[]数组的定义我们可以知道,str2[i2]位置的前面有一坨字符串和str2[0]~str2[next[i2-1]]这一坨是相等的,而既然匹配到了i2这个位置,说明 str1[]有一大坨字符串和整个 str2[0]~str2[i2]这一大坨是相等的,那么我们将 str2往后推,那么 str1有那么一小坨字符串必然和 str2[0]~str2[next[i2-1]]这一小坨相等(最大前缀),那么我们可以从这一坨后面一位开始比较,比较开始的位置就是 next[i2].
  • 跳出比较循环的条件要么是 i1到达了 str1的结尾,要么是 i2到达了 str2的结尾
    • 如果 i2到达了 str2的结尾后面一个,i2==str2.length,说明,整个字符串都匹配完成,返回 i1-i2,否则,返回-1.

附上我潦草的笔记,自己复习回顾用。
这里写图片描述

原创粉丝点击