KMP算法详解,全程无废话,通俗易懂

01.前置知识:字符串的前缀与后缀

如thank,
其前缀有:t,th,tha,than,thank
后缀有:thank,hank,ank,nk,k

02.KMP算法思想及执行流程

思想:每一趟比较中出现字符不等时,不需要回溯索引指针i,而是利用已经得到的部分匹配的结果将子串向右滑动尽可能远的距离,继续进行比较。
在这里插入图片描述
注意:kmp算法中,找的最长公共前后缀:长度要小于比较指针左端子串长度

03.求模式串的next数组

找最长公共前后缀(长度要小于比较指针左端子串长度

3.1案例分析

案例1:abbabaababaa

字符abbabaababaa
索引01234567891011
next[i]000121121211
最长公共前后缀aabaaabaabaa

next数组为:[0, 0, 0, 1, 2, 1, 1, 2, 1, 2, 1, 1]

案例2:ababaaaba

字符ababaaaba
索引012345678
next[i]001231123
最长公共前后缀aababaaaababa

next数组为:[0, 0, 1, 2, 3, 1, 1, 2, 3]
next[j+1]=value的含义:当j个位置发生不匹配时,(模式串中)比较指针回溯到第value个位置

3.2求模式串的next数组的代码

Java语言

	private  int[] kmpNext(String str) {
		int[] next=new int[str.length()];
		for (int i = 1,j=0; i < next.length; i++) {
			while (j>0 && str.charAt(i)!=str.charAt(j)) {
				j=next[j-1];
			}
			if(str.charAt(i)==str.charAt(j)) j++;
			next[i]=j;
		}
		return next;
	}

Scala语言

def kmpNext(str:String):Array[Int]={
      var next=new Array[Int](str.length)
      var j=0

      for (i<-1 until next.length){
        println(str(i)+" "+str(j)+" "+i+" "+j)
        while (j>0 && str(i)!=str(j)){
          j=next(j-1)
        }

        if(str(i)==str(j)){
          j+=1
        }
        next(i)=j
      }
      return next
    }

3.3模式串的next数组代码debug案例分析

假设模式串为“ababaaaba”,则模式串对应的字符数组arr为[a, b, a, b, a, a, a, b, a]

  1. ab: i=1,j=0 next[1]=0
  2. aba: i=2,j=0 arr[2]==arr[0],j++ j=1,next[2]=1
  3. abab: i=3,j=1 arr[3]== arr[1],j++ j=2,next[3]=2 (说明:由于前面已经证明arr[2]=arr[0]==>字符串arr[2]+arr[3]=字符串arr[0]+arr[1]最长公共前缀为2)
  4. ababa: i=4,j=2 arr[4]==arr[2],j++ j=3,next[4]=3
  5. ababaa: i=5,j=3 arr[5]!=arr[3],j=next[j-1]=next[2]=1 下一步=> arr[5]!=arr[1],j=next[j-1]=next[0]=0 下一步=> arr[5]==arr[0],j++ j=1,next[5]=1
  6. ababaaa: i=6,j=1 arr[6]!=arr[1],j=next[j-1]=next[0]=0 下一步=> arr[6]==arr[0],j++ j=1,next[6]=1
  7. ababaaab: i=7,j=1 arr[7]=arr[1],j++ j=2,next[7]=2
  8. ababaaaba: i=8,j=2 arr[8]=arr[2],j++ j=3,next[8]=3

最终next数组为[0, 0, 1, 2, 3, 1, 1, 2, 3]

04.kmp算法实现的全部代码

Java语言

	public int indexOf(String haystack, String needle) {
		if(needle.length()==0) return 0;
		int[] next=kmpNext(needle);//获取next数组
		for (int i = 0,j=0; i < haystack.length(); i++) {
			while (j>0 && haystack.charAt(i)!=needle.charAt(j)) {
				j=next[j-1];
			}

			if(haystack.charAt(i)==needle.charAt(j)) j++;			
			if(j==needle.length()) return i-j+1;
		}
		return -1;
    }
	private  int[] kmpNext(String str) {
		int[] next=new int[str.length()];
		for (int i = 1,j=0; i < next.length; i++) {
			while (j>0 && str.charAt(i)!=str.charAt(j)) {
				j=next[j-1];
			}
			if(str.charAt(i)==str.charAt(j)) j++;
			next[i]=j;
		}
		return next;
	}

Scala语言

	def indexOf(haystack: String, needle: String): Int = {
      if (needle.length == 0) return 0
      var next=kmpNext(needle)//获取next数组
      var j=0
      for(i<-0 until haystack.length){
        while (j>0 && haystack(i)!=needle(j)) {
          j=next(j-1)
        }
        if(haystack(i)==needle(j)) j+=1
        if(j==needle.length) return  i-j+1
      }
      return -1
    }
     
    def kmpNext(str:String):Array[Int]={
      var next=new Array[Int](str.length)
      var j=0

      for (i<-0 until next.length){

        while (j>0 && str(i)!=str(j)){
          j=next(j-1)
        }

        if(str(i)==str(j)) j+=1
        next(i)=j
      }

      return next
    }

05.深入练习:

实现 strStr()
最长快乐前缀

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值