KMP算法

字符串中找字串索引

暴破,直接处理从最开始匹配,从0-n开始循环查找,不相等重新计算
时间复杂度:O(n*m)

KMP算法处理找字符串中字串索引

如图:当"ABCDAB "失配时,直接移动到和"AB ABCD"处比较。



怎么知道移动位置?
失配处为D,D之前字符串为"ABCDAB",而"ABCDAB" 的前缀匹配为AB,那么"ABCDAB "字符串" "(空格)之前的2为"AB"和需要找的字符串"ABCDABD"的前2为一定相同。如果为0,则直接直接移动到空格处开始比较。

public Integer indexSubStr(String s, String subStr) {
        int[] f = calculateTable(subStr);

        int j = 0;
        for (int i = 0; i < s.length(); ) {
            if (s.charAt(i) == subStr.charAt(j)) {
                j++;
                if (j == subStr.length()) {
                    return i - (j - 1);
                }
                i++;
            } else {
                // 第一位没匹配成功,i++继续从j=0即字串第1位开始匹配
                if (j == 0) {
                   i++;
                } else {
                    // 有匹配成功的前缀,i不变,对齐匹配成功的前缀
                    // 匹配到"BBC ABCDAB "和"ABCDABD"时," "和"D"不等
                    // 但"D"前缀f[j-1]为2即"AB",i不动继续和"ABCDABD"前缀之后比较,即"BBC ABCDAB "的"AB "和"ABCDABD"的"ABC"比较
                    j = f[j - 1];
                }
            }
        }

        return -1;
    }


关键计算前缀匹配表算法


思路

cacacabc
caca
  caca

此时匹配成功,匹配+1

cacacabc
cacac
  cacab

不匹配找更短的匹配串,cacac和cacab因为不匹配找更短的,即前缀cacac的更短的串caca和cacab更短的串,有相同更短的串caca。caca是已经匹配了的前缀,length = 4,而caca的匹配度等于匹配表中f[4-1]=f(3)位置

  1. 所以cacac匹配失效时,减少1个匹配度,即已经匹配了的caca的匹配度
  2. 如果cacac的串caca无匹配前缀即时匹配为0,表示cacab的前缀串caca无法和当前比较字符串匹配,结束,直接从失配处和子串第一位重新开始匹配;
  3. 如果cacac的caca前缀有匹配,那么假设匹配2位表示cacab和前缀caca也匹配2位即ca,那么比较第三位b和当前比较字符串第三位
  4. 如果匹配则匹配度是3位,即匹配为2+1=3,匹配到cab
  5. 如果不匹配则继续找前缀ca的前缀匹无匹配结束有匹配继续和b比较,如此匹配一直循环下去
public int[] calculateTable(String subStr) {
        // 计算table
        int[] f = new int[subStr.length()];
        f[0] = 0;
        int t = 0;
        char temp;
        for (int i = 1; i < subStr.length(); i++) {
            temp = subStr.charAt(i);
            if (temp == subStr.charAt(t)) {
                f[i] = ++t;
            } else {
                while (t > 0) {
                    // 假设到b不匹配,b之前匹配度为caca即t,t=4
                    // 拿caca继续找匹配度(索引从0开始)t=f[t-1]=f[3]=2,s[t]=s[2]=c≠b
                    // 拿ca继续找t=f[t-1]=f[1]=0匹配度为0结束
                    t = f[t - 1];
                    if (t >= 0) {
                        if (temp == subStr.charAt(t)) {
                            f[i] = ++t;
                            break;
                        }
                    }
                }
            }
        }
        return f;
    }

借鉴

shortest-palindrome-solution中KMP图解
KMP算法详解 前面讲移动很清晰,讲计算table不结合KMP图解中的图看更清楚

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 文章大纲:1.KMP算法概念2.KMP算法中最核心的next[] 数组是如何生成的3.使用KMP算法 匹配字符串 ...
    柠檬乌冬面阅读 867评论 0 3
  • 参考课程:宋会英老师——KMP算法——效率较高的匹配算法D.E.Knuth,J.H.Morris和V.R.Prat...
    jenye_阅读 2,356评论 0 6
  • 在看算法基础书籍时,看到KMP算法的解释是用的DFA(有限状态自动机),看的我一脸懵逼。所以,就去网上搜索有没有更...
    蘑菇君的小小世界阅读 2,248评论 0 32
  • 一、定义 KMP(Knuth-Morris-Pratt)算法,其实是对暴力查找算法的优化。在暴力查找算法中,用于追...
    null12阅读 891评论 0 0
  • 参考文章 知乎:如何更好的理解和掌握 KMP 算法?从头到尾彻底理解KMPKMP 算法(1):如何理解 KMP(原...
    Mjolnir1107阅读 1,228评论 0 0

友情链接更多精彩内容