日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

KMP算法的学习经验

發(fā)布時間:2024/1/17 65 豆豆
生活随笔 收集整理的這篇文章主要介紹了 KMP算法的学习经验 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

KMP算法的學(xué)習(xí)經(jīng)驗(yàn)

(歡迎指正錯誤, 歡迎噴)

  • 什么是kmp(完)
  • kmp的額外知識(完)
  • 暴力匹配的缺點(diǎn),和代碼實(shí)現(xiàn)(完)
  • next[]數(shù)組的預(yù)先知識,了解前后綴,相同前后綴。(完)
  • kmp的關(guān)鍵next[]數(shù)組, next的實(shí)現(xiàn)。(完)
  • next數(shù)組中k = next[k]的理解。
  • kmp的優(yōu)化(待續(xù)。。)
  • 一.什么是kmp

    KMP算法是一種改進(jìn)的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同時發(fā)現(xiàn),因此人們稱它為克努特——莫里斯——普拉特操作(簡稱KMP算法)。KMP算法的關(guān)鍵是利用匹配失敗后的信息,盡量減少模式串與主串的匹配次數(shù)以達(dá)到快速匹配的目的。具體實(shí)現(xiàn)就是實(shí)現(xiàn)一個next()函數(shù),函數(shù)本身包含了模式串的局部匹配信息。時間復(fù)雜度O(m+n)
    ————來自百度百科
    簡單的說 :
    1.kmp是一種字符串匹配算法。
    2.它的優(yōu)點(diǎn)就是能通過 next[]數(shù)組(一個記憶數(shù)組),減少匹配的次數(shù), 從而節(jié)省時間。
    3.關(guān)鍵是next[] 這個記憶數(shù)組。

    二.kmp的額外知識

    由D.E.Knuth,J.H.Morris和V.R.Pratt同時發(fā)現(xiàn),因此人們稱它為克努特——莫里斯——普拉特操作(簡稱KMP算法)
    并且kmp被很多人叫做,看(k)毛(m)片(p)算法。

    三.普通暴力匹配


    //ptr[] 匹配串, str[] 主串

    1.暴力匹配
    我們的普通暴力匹配是 匹配串ptr 的字符一個一個和 主串匹配。
    如果一個字符匹配成功:ptr的下一個字符繼續(xù)匹配,
    如果失敗 :str[]回溯到開始匹配的位置(i = i - j, <-下面有講解),然后再以 下一個位置為開始, 再次重新進(jìn)行字符串匹配。

    暴力匹配代碼:

    int plen = strlen(ptr);//匹配串的長度 int slen = strlen(str);//主串的長度 int i, j = 0; //i 和j 分別代表 當(dāng)前 str 和ptr 所匹配的字符下標(biāo) int flag = 0;//如果為 1 表示 主串中存在 匹配串。 for(i = 0;i < slen;i++) {if(str[i] == ptr[j])//如果匹配成果 繼續(xù)下一個匹配{j++;}else//如果 不相等 {i = i- j;//主串回溯, i回到匹配前的位置j = 0;//匹配串 要從頭開始}if(j == plen)// 主串中存在客串 匹配串成功{flag = 1;break;//結(jié)束} }

    以上是暴力匹配 的代碼, 這也能解決字符串匹配的問題(這種方法沒有一點(diǎn)錯誤), 然而你用這種方法去解題,很多題只能送你個:

    acmer的你,看到這就是很尷尬了。
    為什么呢?
    因?yàn)槟惚┝ζヅ涮つ苛?#xff0c; 而kmp確實(shí)聰明的 kmp的j知道往哪跳。

    四. 相同前后綴的講解:

    1.什么是前后綴。
    如:ABCD這個字符串
    A
    AB
    ABC
    就是他的前綴。

    BCD
    _CD
    __ D
    就是它的后綴。
    ·下劃線只是營造效果, 沒有意義。

    2.相同前后綴:
    如:ABCAB這個字符串
    AB(前綴) AB(后綴) 就是相似前后綴(而且AB是最長的相似前后綴)。

    五.kmp的next數(shù)組

    kmp 通過next數(shù)組, 保留了ptr(匹配串)以每個字符結(jié)尾的子串的 最長相同前后綴的長度。通過next 主串就不用回溯, 只需ptr(匹配串)來回的跳(有想法的跳 o(* ̄︶ ̄ *)o)就行。
    {
    如:1. 主串ABCABCABD 客串ABCABD
    2.當(dāng)匹配到:
    ABCABCABD
    ABCABD 與其失配。
    但是我們已經(jīng)匹配了ABCABCABD 這個AB 我們已經(jīng)知道他匹配,
    所以根據(jù)ptr的 前后綴相似的性質(zhì)(ABCABD), 直接跳到相似前綴的哪里 接著往后匹配。
    所以就要知道next數(shù)組怎么獲得。

    }

    那么接下來就看個有圖的栗子(例子): 主串:ABABAC 匹配串: ABAC

    /***next數(shù)組的獲取*/ int Get_next() {int plen = strlen(ptr);next[0] = -1;int k = -1;//表示上一次匹配的最長前后綴長度for(i = 0; i < plen; i++){if(k == -1 || ptr[i] == ptr[k])// ptr[i]是后綴的對后一個字符, ptr[k]是前綴的最后一個字符。 k = -1是以第一個字符結(jié)尾的子字符串沒有前后綴,因此就要有個操作, 解決 第一個字符串就匹配失敗的情況。{k++;//如果本次匹配成功 , 長度加一next[i+1] = k;//數(shù)組儲存}else//不成功{i--;//主串不動k = next[k];//長度縮減再次匹配, 對于k為什么等于next[k] ,后續(xù)會有講解。}} } /***kmp 匹配過程****/ int kmp(char str[], char ptr[]{int flag = 0; // flag = 1 表示 主串中含有 匹配串int slen = strlen(str);int plen = strlen(ptr);int i, j = 0;for(i = 0;i < slen;i++){if(j == -1||str[i] == ptr[j])//j == -1是:當(dāng)?shù)谝粋€字符串就不匹配時, 整個匹配串要整體往右移一個。{j++;}else {i--;j = next[j];//匹配失敗 j 跳到一上一個字母結(jié)尾的前綴后面+1處,}if(j == plen){flag = 1;break;}}return flag; }

    六. k = next[k]的理解:

    其他大佬對k = next的理解入口->
    本人的講解:
    當(dāng)匹配失敗時 主串 i會停留不動,
    k 會都等于 next[k]。

    一下圖片是 AAACAAAA和它next[]數(shù)組情況正確

    接下來是過程

    深入了解kmp 請看大牛的講解->

    轉(zhuǎn)載于:https://www.cnblogs.com/TJack/p/10526956.html

    總結(jié)

    以上是生活随笔為你收集整理的KMP算法的学习经验的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。