算法设计与分析 KMP算法

简介: 算法设计与分析 KMP算法

KMP算法

概述

  • KMP问题:字符串str1和str2,str1是否包含str2,如果包含返回str2在str1中的开始位置,如何做到时间复杂度为O(n)
  • 常规思路:从str1的头的尾的字符依次作为str2的开头进行测试,时间复杂度为O(N * M),N:为str1的长度,M:为str2的长度
  • KMP方法的比较方式借鉴了常规方法只是在常规方法的基础上进行加速,每一次比较的出发点可以根据上一次比较得到的数据进行优化,减少比较次数,从而在时间复杂度上进行提升

KMP思路

  • 最长前缀与后缀的匹配长度:在不取到前后长度完全相同之前时,前后缀相同能达到的最大长度
    image.png
    如上图:k的下标为3
  • nextArr数组:对str2求对应所有字符的最长前缀与后缀匹配长度,规定:0位置为 -1;1位置为 0image.png
  • str1从 i 位置与str2比较,在str1的x位置与str2的y位置发生不匹配现象
    image.png
    常规思路:str1中x位置跳回 i + 1位置,str2中y位置跳回 0 位置,重新开始比较
    image.png
    KMP思路:得到y位置对应nextArr数组的值,找到y匹配度前面相同的一截;将str1停留在x位置(KMP中str1的x位置只会往后走,绝对不会在退到前面重新比较),str2由y位置移动到前面相同位置的后一位,开始比较image.png
  • 解析:因为nextArr,str2中有两段相同,在str1的 j 位置开始是与str2中的后缀相同的,所以可以直接将str2从str1 的 i 位置推到 j 位置,又因为前后缀相同直接从str2前缀相同的下一位与str1的 x位置进行比较image.png
  • 例:str1 的 e 与 str2 的 w不相等
    image.png
    第一次跳跃:找到str2的w 位置的nextArr数组对应的值,此时str2 的 t 位置与str 1的 e位置开始比较,相当于:将str2移动到str1中第二个框住 a的位置比较,又因为有一部分相同,所以是 t 位置与 e 位置的比较
    image.png
    第二次跳跃:t 与 e 又不相同,找到str2的t位置的nextArr数组对应的值,str2 的s位置与 str1的e位置比较image.png
    第三次跳跃:s 又与 e不同,此时s的nextArr为0,则跳回str2的开头位置与 e 比较,还是不同,将str1到e的下一个位置,重新开始image.png

代码实现

  • nextArr数组的求法
    (1)0位置:-1,1位置:0
    (2)x位置是:n,若x位置与前缀的下一个位置相同,则x + 1位置就是:n + 1;若x位置与前缀的下一个位置不同,前缀下一个位置为:m,就跳到前缀的前缀,若相同,则x + 1位置就是:m+ 1,若不同继续先前找前缀……直到找到最前面若x与最前面相同, x + 1位置就是:1,不同就是0
  • 例:image.png

x 的nextArr位置为8,确定 x + 1的nextArr位置就是又x的值决定

(1)若 x 为 e,则 ? 为 x 的nextArr + 1,为 9

(2)若 x 不为 e,就跳到 s 与其比较,若相同 ? 是 e 的nextArr + 1为 4

(3)若 x 不为 s,就跳到最前面 a 比较,若相同 ? 是 s 的nextArr + 1为 1

(4)若 x 不为 a,就是 0

求解 next 数组
    public static int[] getNextArray(char[] str) {
        if (str.length == 1){
            return new int[] {-1};
        }
        //默认,0位置是-1,1位置是1
        int[] nextArr = new int[str.length];
        nextArr[0] = -1;
        nextArr[1] = 1;
        int index = 2; //next数组的位置
        int pre = 0; //要比较字符的位置(前缀的下一个)也有前缀长度的含义
        while (index < str.length){
            //时间复杂度为:O(M),M = chs1.length
            if (str[index - 1] == str[pre]){
                //index - 1 与 pre 位置相同
                //nextArr[index] 就是上一个位置加一
                //pre:前缀长度增加
                nextArr[index] = nextArr[index - 1] + 1;
                index++;
                pre++;
            } else if (pre > 0){
                //不相同,跳到上一个前缀进行比较
                pre = nextArr[pre];
            }else {
                //跳到了最前面,也不相同
                nextArr[index] = 0;
                index++;
            }
        }
        return nextArr;
    }
kmp代码
    public static int kmp(String str1, String str2){
        //匹配成功,返回str1中匹配str2成功的位置,否则返回 -1
        if (str1 == null || str2 == null || str1.length() < 1 || str2.length() < 1){
            return -1;
        }
        char[] chs1 = str1.toCharArray();
        char[] chs2 = str2.toCharArray();
        int index1 = 0;
        int index2 = 0;
        int[] next = getNextArray(chs2);
        while (index1 < chs1.length && index2 < chs2.length){
            //时间复杂度为:O(N),N = chs2.length
            //若是因为index2 == chs2.length结束while,说明匹配成功
            //若只是因为index1 == chs1.length结束while,说明整个匹配失败
            if (chs1[index1] == chs2[index2]){
                index1++;
                index2++;
            } else if (index2 == 0){
                //等同与:else if (next[index2] == -1)
                //index2回到0位置,且str1仍不匹配,直接使index1移动
                index1++;
            } else {
                //index2的跳跃,就是对应下标next数组中的值
                index2 = next[index2];
            }
        }
       //判断是否匹配成功
        return index2 == chs2.length ? index1 - index2 : -1;
    }


目录
相关文章
|
1月前
|
机器学习/深度学习 人工智能 监控
AI算法分析,智慧城管AI智能识别系统源码
AI视频分析技术应用于智慧城管系统,通过监控摄像头实时识别违法行为,如违规摆摊、垃圾、违章停车等,实现非现场执法和预警。算法平台检测街面秩序(出店、游商、机动车、占道)和市容环境(垃圾、晾晒、垃圾桶、路面不洁、漂浮物、乱堆物料),助力及时处理问题,提升城市管理效率。
AI算法分析,智慧城管AI智能识别系统源码
|
1月前
|
算法
经典控制算法——PID算法原理分析及优化
这篇文章介绍了PID控制算法,这是一种广泛应用的控制策略,具有简单、鲁棒性强的特点。PID通过比例、积分和微分三个部分调整控制量,以减少系统误差。文章提到了在大学智能汽车竞赛中的应用,并详细解释了PID的基本原理和数学表达式。接着,讨论了数字PID的实现,包括位置式、增量式和步进式,以及它们各自的优缺点。最后,文章介绍了PID的优化方法,如积分饱和处理和微分项优化,以及串级PID在电机控制中的应用。整个内容旨在帮助读者理解PID控制的原理和实际运用。
87 1
|
1天前
|
算法 数据可视化 大数据
圆堆图circle packing算法可视化分析电商平台网红零食销量采集数据
圆堆图circle packing算法可视化分析电商平台网红零食销量采集数据
30 13
|
7天前
|
算法 数据可视化 Python
Python中LARS和Lasso回归之最小角算法Lars分析波士顿住房数据实例
Python中LARS和Lasso回归之最小角算法Lars分析波士顿住房数据实例
13 0
|
8天前
|
算法 定位技术 Windows
R语言最大流最小割定理和最短路径算法分析交通网络流量拥堵问题
R语言最大流最小割定理和最短路径算法分析交通网络流量拥堵问题
13 4
|
9天前
|
存储 算法
图解Kmp算法——配图详解(超级详细)
图解Kmp算法——配图详解(超级详细)
|
14天前
|
算法 测试技术 C#
【字典树】【KMP】【C++算法】3045统计前后缀下标对 II
【字典树】【KMP】【C++算法】3045统计前后缀下标对 II
|
14天前
|
算法
【算法学习--字符串】(不含KMP算法)
【算法学习--字符串】(不含KMP算法)
|
30天前
|
算法
TOP-K问题和向上调整算法和向下调整算法的时间复杂度问题的分析
TOP-K问题和向上调整算法和向下调整算法的时间复杂度问题的分析
19 1
|
1月前
|
算法
PID算法原理分析及优化
这篇文章介绍了PID控制方法,一种广泛应用于机电、冶金等行业的经典控制算法。PID通过比例、积分、微分三个部分调整控制量,以适应系统偏差。文章讨论了比例调节对系统响应的直接影响,积分调节如何消除稳态误差,以及微分调节如何减少超调。还提到了数字PID的实现,包括位置式、增量式和步进式,并探讨了积分饱和和微分项的优化策略。最后,文章简述了串级PID在电机控制中的应用,并强调了PID控制的灵活性和实用性。
39 1