KMP算法

字符串中找字串索引

暴破,直接處理從最開始匹配,從0-n開始循環(huán)查找,不相等重新計算
時間復(fù)雜度:O(n*m)

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

如圖:當(dāng)"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++繼續(xù)從j=0即字串第1位開始匹配
                if (j == 0) {
                   i++;
                } else {
                    // 有匹配成功的前綴,i不變,對齊匹配成功的前綴
                    // 匹配到"BBC ABCDAB "和"ABCDABD"時," "和"D"不等
                    // 但"D"前綴f[j-1]為2即"AB",i不動繼續(xù)和"ABCDABD"前綴之后比較,即"BBC ABCDAB "的"AB "和"ABCDABD"的"ABC"比較
                    j = f[j - 1];
                }
            }
        }

        return -1;
    }


關(guān)鍵計算前綴匹配表算法


思路

cacacabc
caca
  caca

此時匹配成功,匹配+1

cacacabc
cacac
  cacab

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

  1. 所以cacac匹配失效時,減少1個匹配度,即已經(jīng)匹配了的caca的匹配度
  2. 如果cacac的串caca無匹配前綴即時匹配為0,表示cacab的前綴串caca無法和當(dāng)前比較字符串匹配,結(jié)束,直接從失配處和子串第一位重新開始匹配;
  3. 如果cacac的caca前綴有匹配,那么假設(shè)匹配2位表示cacab和前綴caca也匹配2位即ca,那么比較第三位b和當(dāng)前比較字符串第三位
  4. 如果匹配則匹配度是3位,即匹配為2+1=3,匹配到cab
  5. 如果不匹配則繼續(xù)找前綴ca的前綴匹無匹配結(jié)束有匹配繼續(xù)和b比較,如此匹配一直循環(huán)下去
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) {
                    // 假設(shè)到b不匹配,b之前匹配度為caca即t,t=4
                    // 拿caca繼續(xù)找匹配度(索引從0開始)t=f[t-1]=f[3]=2,s[t]=s[2]=c≠b
                    // 拿ca繼續(xù)找t=f[t-1]=f[1]=0匹配度為0結(jié)束
                    t = f[t - 1];
                    if (t >= 0) {
                        if (temp == subStr.charAt(t)) {
                            f[i] = ++t;
                            break;
                        }
                    }
                }
            }
        }
        return f;
    }

借鑒

shortest-palindrome-solution中KMP圖解
KMP算法詳解 前面講移動很清晰,講計算table不結(jié)合KMP圖解中的圖看更清楚

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 文章大綱:1.KMP算法概念2.KMP算法中最核心的next[] 數(shù)組是如何生成的3.使用KMP算法 匹配字符串 ...
    檸檬烏冬面閱讀 865評論 0 3
  • 參考課程:宋會英老師——KMP算法——效率較高的匹配算法D.E.Knuth,J.H.Morris和V.R.Prat...
    jenye_閱讀 2,352評論 0 6
  • 在看算法基礎(chǔ)書籍時,看到KMP算法的解釋是用的DFA(有限狀態(tài)自動機(jī)),看的我一臉懵逼。所以,就去網(wǎng)上搜索有沒有更...
    蘑菇君的小小世界閱讀 2,246評論 0 32
  • 一、定義 KMP(Knuth-Morris-Pratt)算法,其實是對暴力查找算法的優(yōu)化。在暴力查找算法中,用于追...
    null12閱讀 888評論 0 0
  • 參考文章 知乎:如何更好的理解和掌握 KMP 算法?從頭到尾徹底理解KMPKMP 算法(1):如何理解 KMP(原...
    Mjolnir1107閱讀 1,224評論 0 0

友情鏈接更多精彩內(nèi)容