• 算法-KMP


        KMP算法的作用在于在一个主串中查找一个主串。

    传统查找子串的方法是一个字符一个字符的比较,代码如下:

     public static int notKMP(String main,String sub){
    
            for (int i=0;i<main.length();i++){
                int j=0;
                int k=i;
                while (main.charAt(k)==sub.charAt(j)){
                    k++;
                    j++;
                    if (j==sub.length()){
                        return i;
                    }
                }
            }
            return -1;
    
        }

    这种方式在遇到不相同的时候,主串往下移动一位,子串恢复到0.继续的进行对比。

    KMP的算法的有点在于子串中如果有相同的部分的话,那么可以省略一部分的校验,下面这个图加深一些印象:

    如果我们使用KMP算法的话,那么中间的红框的那部分是不需要比较的,很显而易见,因为他们都第一步进行了比较了,当然怎么判断还是需要算法的。

    算法的步骤分为两部分,第一部分是算出子串的next数组,这个数组表达的就是子串的相似度,具体算法实现:

     /**
         * 返回KMP数组
         * @param str
         * @return
         */
        public static int[] getNextArr(String str){
            int[] nexts=new int[str.length()];
            //j=1 的时候为0  j=2的时候为1
            nexts[0]=0;
            nexts[1]=1;
            for (int j=2;j<str.length();j++){
                int index=1;
                for (int i=0;i<j-1;i++){
                    if(str.substring(0,i+1).equals(str.substring(j-i-1,j))){
                        index++;
                    }
                }
                nexts[j]=index;
            }
            return nexts;
        }

    第二部分就是进行匹配:

     /**
         *
         * @param s 主串
         * @param t 子串
         * @param pos 从主串哪个位置开始匹配
         * @return
         */
        public static int indexKMP(String s,String t,int pos){
            int i=pos;
            int j=0;
            int[] nexts=getNextArr(t);
            while (i<s.length()&&j<t.length()){
                if (j==0||s.charAt(i)==t.charAt(j)){
                    i++;
                    j++;
                }else {
                    j=nexts[j-1];
                }
            }
    
            if (j>=t.length()){
               return i-t.length();
            }
            return 0;
        }

    . 总的来讲就是只关注子串,出现相同的那部分可以不进行比较。

  • 相关阅读:
    BZOJ3832: [Poi2014]Rally(拓扑排序 堆)
    UVAlive6807 Túnel de Rata (最小生成树)
    UVAlive6800The Mountain of Gold?(负环)
    cf623A. Graph and String(二分图 构造)
    BZOJ4144: [AMPPZ2014]Petrol(最短路 最小生成树)
    cf605D. Board Game(BFS 树状数组 set)
    为什么要去创业?
    后缀数组练习题若干
    Android开发 之 我的jar包引用方法
    IBM-ETP 实训项目前一天
  • 原文地址:https://www.cnblogs.com/zr520/p/6596334.html
Copyright © 2020-2023  润新知