zoukankan      html  css  js  c++  java
  • KMP算法分析

    1、问题出现

    给出一个字符串为source,和另一个字符串target。

    如果这个target是source的字串,返回这个子串的开始的索引。如果不是子串则返回-1。

    2、解决问题的思路

    任何一个算法都说从暴力法优化得到的,KMP算法也不例外。这次我们列出暴力法如下:

     1 public class KMP {
     2     public static int match(String source,String target) {
     3         int i=0;//原字符串的下标
     4         int j=0;//目标子串的下标
     5         int k=-1;//记录第几个字符
     6         while(i<source.length()) {
     7             while(j<target.length()&&source.charAt(i)==target.charAt(j)) {
     8                 i++;
     9                 j++;
    10             }//子串和目标串进行匹配
    11             k++;//首字符位置每次循环后+1。
    12             if(j==target.length()) {
    13                 return k;
    14             }else {
    15                 j=0;
    16                 i=k+1;
    17             }
    18             
    19         }
    20         return -1;
    21     }
    22     public static void main(String[] args) {
    23         System.out.println(match("abababca","bab"));
    24     }
    25 }
     

    这个算法有俩层循环嵌套显得十分臃肿。这时候就需要对算法进行优化。

    3、KMP算法的引入

    上面的算法每次匹配失败之后,我们会都移动i和j。

    而KMP则只需要我们每次只移动需要匹配的字串的j 不移动原字符串的i。这样就少了一层循环。

    那j需要移动到哪呢?KMP为原字符串准备了个next数组。

    先不用管如何实现的。我们先试试这个方法。

    public class KMP2 {
        static int[] next = {-1,0,0,1,2,3,4,0};
        public static int match(String source,String target){
            int i=0;
            int j=0;
            
            while(i<source.length()) {
                if(j == -1 ||source.charAt(i)==target.charAt(j)) {
                    i++;
                    j++;
                }
                else {
                    j=next[j];//这里我们只给j赋值
                }
                if(j==target.length()) {
                    return i-j;//返回匹配开头的字符
                }
            }
            return -1;
        }
        public static void main(String[] args) {
            System.out.println(match("abababca","bab"));
        }
    }

    结果是一样的。这就少了一层循环。

    4、NEXT数组如何求的呢?

    总共分4步骤

    1、找字符串的前缀式:例如 aba这个 前缀式就是a、ab

    2、找字符串的后缀式:例如 aba这个字符串的后缀式为ba、a

    3、找前后俩个字符串相同的最长字串、的长度,这里的aba中a相同,因此就是1

    但是如果未找出就得0;

    如上所示。

    4、把我们之前求的数,向右移。一位就是next数组了。

    此图像的alt属性为空;文件名为@W6IAKAKJ855TKGFEKOZ7.png

    如果之前没做过的,一定要手动算一下。算完了就记住了。

    5、算法求出NEXT数组。

    算法实现是个难理解的地方。

    记住俩概念:索引值为0和1的俩个数设为-1和0,不为什么。记住

    public class KMP2 {
        //static int[] next = {-1,0,0,1,2,3,4,0};
        public static int[] getNext(String source)
        {
            int[] next = new int[source.length()];
            // 初始条件
            int j = 0;
            int k = -1;
            next[0] = -1;
            // 根据已知的前j位推测第j+1位
            while (j <source.length() - 1){
                if (k == -1 || source.charAt(j) ==source.charAt(k)){
                    next[++j] = ++k;
                }
                else{
                    k = next[k];
                }
            }
             return next;
        }
        
        
        public static int match(String source,String target){
            int i=0;
            int j=0;
            int[] next = getNext(source);
            while(i<source.length()) {
                if(j == -1||source.charAt(i)==target.charAt(j)) {
                    i++;
                    j++;
                }
                else {
                    j=next[j];
                }
                if(j==target.length()) {
                    return i-j;
                }
            }
            return -1;
        }
        public static void main(String[] args) {
            System.out.println(match("abababca","bab"));
        }
    }

  • 相关阅读:
    unexpected inconsistency;run fsck manually esxi断电后虚拟机启动故障
    centos 安装mysql 5.7
    centos 7 卸载mysql
    centos7 在线安装mysql5.6,客户端远程连接mysql
    ubuntu 14.04配置ip和dns
    centos7 上搭建mqtt服务
    windows eclipse IDE打开当前类所在文件路径
    git 在非空文件夹clone新项目
    eclipse中java build path下 allow output folders for source folders 无法勾选,该如何解决 eclipse中java build path下 allow output folders for source folders 无法勾选,
    Eclipse Kepler中配置JadClipse
  • 原文地址:https://www.cnblogs.com/godoforange/p/10834703.html
Copyright © 2011-2022 走看看