让我们来写个算法吧,(3)字符串匹配之KMP算法

   字符串的匹配是非常常用的一项技术,我们来思考下面一个场景

   现在有给定字符串 ABCDEFGABCDA

     匹配字符串 ABCDA

  我们按照一般思路,暴力匹配。于是得出了以下的代码

   

public int bfSearch(String txt ,String pat) {
        
        int tLen = txt.length();
        int pLen = pat.length();
        int i ;
        int j ;
        for ( i = 0; i < tLen; i++) {
            for ( j = 0; j < pLen && i< tLen; j++) {
                if(txt.charAt(i) == pat.charAt(j)) {
                    i++;
                }else {
                    break;
                }
            }
            if(j == pLen) {
                return  i -j;
            }else {
                i = i-j;
          j = 0; } }
return -1; }

   此方法可以实现,但是有个效率上的问题就是,第一次匹配 i=0 到上串ABCDE 与下串ABCD ,我们认为匹配失败,上串的i 下标返回到2继续匹配,但是我们已经知道前4个已经匹配过不用再次匹配。所以我们有没有一种算法可以回溯 i 下表到第5位呢???

  由此大名鼎鼎的KMP算法就由此引出来了,如何让i下标不回溯,只跑 j 下标呢。核心就是引出一个 next [] 用来记录j下标的回溯策略。具体的原理和思路本人不再阐述给你们几篇写的好的连接

  https://www.cnblogs.com/zhangtianq/p/5839909.html

  我们这边直接上代码 

  

    public int kmpSearch(String txt , String pat) {
        
        int tLen = txt.length();
        int pLen = pat.length();
        int [] next = getNext(pat);
        for (int i : next) {
            System.out.print(i+" ");
        }
        System.out.println();
        int i = 0;
        int j = 0;
        while(i < tLen) {
            System.out.println("第 "+i+" 次 i= " +i +" ,j= "+j);
            if(j == -1 || txt.charAt(i) == pat.charAt(j)) {
                ++i;
                ++j;
            }else {
                j = next[j];
            }
            
            
        }
        
        
        return j == pLen ? i-j : -1;
    }
    
    public int[] getNext(String pat) {
        
        int length = pat.length();
        int [] next = new int[length];
        
        next[0] = -1;
        
        int k= -1;
        int j = 0;
        
        while(j<length-1) {
            
            if(k==-1 || pat.charAt(k) == pat.charAt(j)) {
                ++k;
                ++j;
                next[j]=k;
            }else {
                k = next[k];
            }
            
        }
        return next;
    }

  主要在于求出next数组,让i指针不回退,只用寻找j指针的回推策略。

posted on 2020-03-03 22:01  闯入你笑颜  阅读(107)  评论(0编辑  收藏  举报

导航