1. 程式人生 > >簡單的KMP演算法

簡單的KMP演算法

雖然題目聲稱KMP簡單,但只是對於理解了的人而言的,但是對於還沒有理解的人來說,KMP演算法確實是非常難的,但是不要緊,我相信通過我的介紹你會理解的,但是個人認為,不論什麼比較難理解的演算法,如果直接給你講,即使講的方法再簡單,但是你沒有去自己思考,那也是理解不了的,就像做一道特別難的數學題,你想了幾個小時還是沒有做出來,但是這時候當別人給你說的時候,你可能會豁然開朗,這是因為你前面幾個小時的思考起到的關鍵性作用,所以對於任何演算法你都要先試圖自己去思考單獨,最後實在想不出來再去看看別人的想法,你會更加容易理解,好了,廢話不多說,下面就來詳細說說KMP演算法:

(一)字首和字尾 ,這個不用說太多解釋,直接上一個人例題你就會明白,

(1)以”ABCDABD”為例,”ABCDABD”的字首為[A, AB, ABC, ABCD, ABCDA, ABCDAB],字尾為[BCDABD, CDABD, DABD, ABD, BD, D]
(2)又如:字串ABCAB 字首:{A, AB, ABC, ABCA}字尾:{BCAB, CAB, AB, B}

字首與字尾的作用其實就是找到相同的元素長度,在進行比較的字串的時候,可以直接進行相同元素的比較,而不是一步一步返回來比較,因此提高了匹配效率。

(二)知道了字首和字尾,我們就來看看如何利用他們進行字串的匹配,以字串”BBCABCDABABCDABCDABDE”和”ABCDABD”來進行匹配。

(1)首先,字串”BBC ABCDAB ABCDABCDABDE”的第一個字元與搜尋詞”ABCDABD”的第一個字元比較,不匹配,移到下一個字元

(2)不匹配,以一個字元比較

(3)移到A時候,這時候匹配了

(4)此時直到D所對應的不匹配了,這時候該怎麼辦呢,

(5)這時,最自然的反應是,將搜尋詞整個後移一位,再從頭逐個比較。這樣做雖然可行,但是效率很差,因為你要把”搜尋位置”移到已經比較過的位置,重比一遍。

(6)但是你感覺這樣好嗎?肯定是不好的,那該怎麼辦呢,這時候字首和字尾就派上用場了,我們不需要直接從頭比較,我們只要直接比較相同元素就可以了,因為這時候又重新達到了一個匹配。

(三)由於需要每次匹配需要一個指示位置,這時候就需要一個next陣列,直到著當不匹配時候,該如何比較:以上面為例子:

“部分匹配值”就是”字首”和”字尾”的最長的共有元素的長度。以”ABCDABD”為例,
- “A”的字首和字尾都為空集,共有元素的長度為0;
- “AB”的字首為[A],字尾為[B],共有元素的長度為0;
- “ABC”的字首為[A, AB],字尾為[BC, C],共有元素的長度0;
- “ABCD”的字首為[A, AB, ABC],字尾為[BCD, CD, D],共有元素的長度為0;
- “ABCDA”的字首為[A, AB, ABC, ABCD],字尾為[BCDA, CDA, DA, A],共有元素為”A”,長度為1;
- “ABCDAB”的字首為[A, AB, ABC, ABCD, ABCDA],字尾為[BCDAB, CDAB, DAB, AB, B],共有元素為”AB”,長度為2;
- “ABCDABD”的字首為[A, AB, ABC, ABCD, ABCDA, ABCDAB],字尾為[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的長度為0。

(四)程式碼

(1)求next

void makeNext(const char P[],int next[])
{
    int q,k;//q:模版字串下標;k最大前後綴長度
    int m = strlen(P);
    next[0] = 0;
    for (q = 1,k = 0; q < m; ++q)//for迴圈,從第二個字元開始,依次計算每一個字元對    應的next值
    {
        while(k > 0 && P[q] != P[k])
            k = next[k-1];          
        if (P[q] == P[k])
        {
            k++;
        }
        next[q] = k;
    }
} 

(2)求解匹配

 int kmp(const char T[],const char P[],int next[])
 {
     int n,m;
     int i,q;
     n = strlen(T);
     m = strlen(P);
     makeNext(P,next);
     for (i = 0,q = 0; i < n; ++i)
     {
         while(q > 0 && P[q] != T[i])
             q = next[q-1];
         if (P[q] == T[i])
         {
             q++;
         }
         if (q == m)
         {
             printf("Pattern occurs with shift:%d\n",(i-m+1));
         }
     }    
 }

相關推薦

簡單KMP演算法

題目描述: Description 一塊花布條,裡面有些圖案,另有一塊直接可用的小飾條,裡面也有一些圖案。對於給定的花布條和小飾條,計算一下能從花布條中儘可能剪出幾塊小飾條來呢?   Input 輸入中含有一些資料,分別是成對出現的花布條和小飾條,其布條都是用可見ASCII

KMP演算法簡單理解 【筆記】

//本文除實現程式碼外全部為原創內容 轉載請註明出處  程式碼來自這裡 kmp演算法是一種改進的字串匹配演算法,由D.E.Knuth與V.R.Pratt和J.H.Morris同時發現,故稱KMP演算法 字串匹配:從字串T中尋找字串P出現的位置(P遠小於T)。其中P稱為“模式”

KMP演算法簡單求next陣列

前言 1.next陣列的計算只與模式串有關,與主串無關 2.next可能有不同的表示方法,但意義不變 3.字首:除最後一個字母外,前面字母的從前往後組合情況。串abaaba的字首={a,ab,aba,abaa,abaab} 4.字尾:除第一個字母外,後面字母的從前往後組合情況。串

運用kmp演算法解決的一些問題的簡單題解

學習kmp演算法我最後是看的資料結構書上的一本教材學會的。。我覺得kmp相對於普通的BF演算法就是避免了很多不必要的匹配,而kmp演算法的精髓自然就在於next陣列的運用。。。而next陣列簡而言之就

簡單理解KMP演算法

KMP演算法是迄今為止最為高效的字串匹配演算法。當然,在KMP演算法出現之前,有關字串的匹配問題當然經過了一個漫長的探索過程。從一開始最簡單的樸素字串匹配演算法,到Rabin-Karp演算法,再到有限自動機演算法等等,可以說任何一個偉大演算法的誕生都不可能是一朝

簡單KMP演算法

雖然題目聲稱KMP簡單,但只是對於理解了的人而言的,但是對於還沒有理解的人來說,KMP演算法確實是非常難的,但是不要緊,我相信通過我的介紹你會理解的,但是個人認為,不論什麼比較難理解的演算法,如果直接給你講,即使講的方法再簡單,但是你沒有去自己思考,那也是理解不

字串匹配演算法——KMP演算法簡單解釋

一、字串匹配演算法KMP KMP演算法是一種改進的字串匹配演算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同時發現,因此人們稱它為克努特——莫里斯——普拉特操作(簡稱KMP演算法)。KMP演算法的關鍵是利用匹配失敗後的資訊,儘量減少模式串

KMP演算法真的很簡單1

KMP 演算法真的很簡單 KMP 是字串匹配的經典演算法,曾經一度對其敬而遠之,感覺很難寫出來正確的 KMP 演算法,這都是拜那些“教科書”所賜,在它們的教授下,不禁感覺 KMP 很難! 其實理解 KMP 演算法很簡單,今天就來看個究竟,我的目標就是從幾個簡單的數學等式

簡單KMP演算法求next陣列值的方法

本文依照嚴蔚敏串的資料結構(C語言版本)總結的方法: next陣列的求解方法是: 注意:1.   j的下標識從0開始排的                 2.  規定next[0]=-1,next[1]=0                   j           

kmp演算法(最簡單最直觀的理解,看完包會)

本文將以特殊的方式來讓人們更好地理解kmp演算法,不包括kmp演算法的推導,接下來,我們將從樸素演算法出發。 在這之前,我們先設主串為S,模式串為T,我們要解決的詢問是主串中是否包含模式串(即T是否為S的子串)。 版權宣告:本文為原創文章,轉載請標明出處。

字串模式匹配(簡單模式匹配演算法KMP演算法)(一)

一般的字串模式匹配演算法是類似下面的逐次匹配,舉例說明如下 主串s=ababcabcacbab 從串t=abcac 一般匹配方法如下圖所示 程式碼如下 int index(string s,string t) {     int i=0,j=0;     int

CSU 1598 最長公共前綴 (簡單KMP或者暴力)

esp ret strlen != main 直接 整數 out get Submit Page Summary Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 226 Solve

HDU 2087 剪花布條 (簡單KMP或者暴力)

string abcde 都沒有 chm strlen oba bre while align 剪花布條 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

簡單演算法初探過程彙編 棧幀指標

從簡單的演算法初探過程彙編 棧幀指標 作者:zcabcd123       從簡單的演算法初探過程彙編 轉載自 搗亂小子   趁年輕,用程式碼實現夢想 — daoluan.net 不忽視彙編   較於我們日常接觸的高階語

KMP演算法之next函式解釋(大量的反證法 和數學歸納法來襲)

先放get_nextval()函式的程式碼 void get_nextval(const char str[],int *net) { net[0]=-1; int j=0,k=-1,len; len=strlen(str); while(j<len)

一文讀懂 KMP 演算法

來源:阮一峰http://www.ruanyifeng.com/blog/2013/05/Knuth–Morris–Pratt_algorithm.html 字串匹配是計算機的基本任務之一。舉例來說,有一個字串"BBC ABCDAB ABCDABCDABDE",我想知道,裡面是否包

KMP演算法與其應用

KMP字串匹配 題目連結:https://www.luogu.org/problemnew/show/P3375 1.nxt陣列: nxt[x]:以x位結尾的字串為字尾能匹配到的最長字首。 求法見程式碼: nxt[1]=0;int j=0; for(int i=2;i<

KMP演算法淺顯理解

說明:轉載 KMP演算法看懂了覺得特別簡單,思路很簡單,看不懂之前,查各種資料,看的稀裡糊塗,即使網上最簡單的解釋,依然看的稀裡糊塗。 我花了半天時間,爭取用最短的篇幅大致搞明白這玩意到底是啥。 這裡不扯概念,只講演算法過程和程式碼理解: KMP演算法求解什麼型別問題 字串匹配。給

hihoCoder week3 KMP演算法

題目連結 https://hihocoder.com/contest/hiho3/problems   kmp演算法 #include <bits/stdc++.h> using namespace std; const int N = 1e6 + 10; cha

KMP演算法(字串)

純模板題:HDU1686 #include<cstdio> #include<cstdlib> #include<cstring> #define INF 1000005 int next[INF]; char a[INF],b[INF]; void