導航:首頁 > 源碼編譯 > dfa實現kmp演算法

dfa實現kmp演算法

發布時間:2022-07-23 05:27:57

Ⅰ kmp 演算法原理

樸素演算法
先看看最「樸素」的演算法: ///find a template in a string. #include<string.h> #include<stdio.h> int Index(char *S, char *T, int pos) { int k=pos, j=0; while(k <strlen(S) && j<strlen(T))//未超出字元串的長度 { if (S[k] == T[j]) { ++k; ++j;} //如果相同,則繼續向後比較 else {k = k-j+1; j =0;} //如果不同,就回溯,重新查找 } if (j == strlen(T)) return k-strlen(T); else return 0; }
編輯本段KMP演算法
一種由Knuth(D.E.Knuth)、Morris(J.H.Morris)和Pratt(V.R.Pratt)三人設計的線性時間字元串匹配演算法。這個演算法不用計算變遷函數δ,匹配時間為Θ(n),只用到輔助函數π[1,m],它是在Θ(m)時間內,根據模式預先計算出來的。數組π使得我們可以按需要,「現場」有效的計算(在平攤意義上來說)變遷函數δ。粗略地說,對任意狀態q=0,1,…,m和任意字元a∈Σ,π[q]的值包含了與a無關但在計算δ(q,a)時需要的信息。由於數組π只有m個元素,而δ有Θ(m∣Σ∣)個值,所以通過預先計算π而不是δ,使得時間減少了一個Σ因子。[1] KMP演算法是通過分析子串,預先計算每個位置發生不匹配的時候,所需GOTO的下一個比較位置,整理出來一個next數組,然後在上面的演算法中使用。
編輯本段KMP演算法的講解
當我們分析一個子串時,例如:abcabcddes. 需要分析一下,每個字元x前面最多有多少個連續的字元和字元串從初始位置開始的字元匹配。然後+1就行了(別忘了,我們的字元串都是從索引1開始的)當然,不要相同位置自己匹配,默認第一個字元的匹配數是0。
編輯本段定義
設字元串為 x1x2x3...xn ,其中x1,x2,x3,... xi,... xn均是字元,設ai為字元xi對應的整數。則a=m,當且僅當滿足如下條件:字元串x1x2...xm equals 字元串x(i-m+1)...xi-1 xi 並且x1x2...xm x(m+1) unequals x(i-m) x(i-m+1)...xi-1 xi。
編輯本段舉例
abcabcddes 0111234111 |----------------------默認是0 --| | |-----------------不能自己在相同位置進行字元匹配,所以這里認為沒有匹配字元串,所以0+1 =1,繼續從1開始匹配 ------| | |-----------前面的字元和開始位置的字元相同,所以是2,3,4 -----------| | | |-------不匹配只能取1。 希望能明白的是,如果開始字元是 Ch1的話,那麼我們就是要在串中第2個Ch1後面的位置開始自己和自己匹配,計算最大的吻合度。 程序寫出來就是: void GetNext(char* T, int *next) { int k=1,j=0; next[1]=0; while( k〈 T[0] ){ if (j ==0 || T[k] == T[j]) { ++k; ++j; next[k] = j; } else j= next[j]; } } 但是這個不是最優的,因為他沒有考慮aaaaaaaaaaaaaaaaaaab的情況,這樣前面會出現大量的1,這樣的演算法復雜度已經和最初的樸素演算法沒有區別了。所以稍微改動一下: void GetNextEx(char *T, char *next) { int k=1,j=0; next[1] = 0; while(k < T[0]) { if (j == 0 || T[k] == T[j]) { ++k; ++j; if (T[k] == T[j]) next[k] = next[j]; else next[k] = j; } else j = next[j]; } } 現在我們已經可以得到這個next字元串的值了,接下來就是KMP演算法的本體了: 相當簡單: int KMP(char* S, char* T, int pos) { int k=pos, j=1; while (k){ if (S[k] == T[j]){ ++k; ++j; } else j = next[j]; } if (j>T[0]) return k-T[0]; else return 0; } 和樸素演算法相比,只是修改一句話而已,但是演算法復雜度從O(m*n) 變成了:O(m)
編輯本段KMP演算法的偽代碼
KMP-MATCHER(T,P) 1n ← length[T] 2m ←length[P] 3π ← COMPUTE-PREFIX-FUNCTION(P) 4q ← 0△Number of characters matched. 5for i ← 1 to n△Scan the text from left to right. 6do while q>0 and P[q+1]≠T[i] 7do q ← π[q]△Next character does not match. 8if P[q+1]=T[i] 9then q ← q+1△Next character matches. 10if q=m△Is all of P matched? 11then print 「Pattern occurs with shift」 i-m 12q ← π[q]△Look for the next match. COMPUTE-PERFIX-FUNCTION(P) 1m ← length[P] 2π[1] ← 0 3k ← 0 4for q ← 2 to m 5do while k>0 and P[k+1]≠P[q] 6do k ← π[k] 7if P[k+1]=P[q] 8then k ← k+1 9π[q] ← k 10return π[1]
編輯本段KMP演算法的c++實現
//c++實現的KMP演算法,所有涉及字元串,其初始下標從0開始(上述演算法均是從1開始) //example: char s[100],t[100];cin>>s>>t;KMP(s,t); //獲取待查詢模式的next數組 int* get_next(char* T, int* next){ int i = 0, j = -1; int length = strlen(T); int *temp = next; *next = -1; while(i< length){ if(j==-1 || *(T+i)==*(T+j)){ i++; j++; //優化後的get_next方法,可以防止出現形如"aaaaab"這種模式的計算退化 if(*(T+i)!=*(T+j)) *(next+i)=j; else *(next+i)=*(next+j); } else j=*(next+j); } return temp; } //KMP演算法 int KMP(char *S, char *T){ int S_Length = strlen(S); int T_Length = strlen(T); //若模式長度大於字元串,則直接返回查詢失敗 if( S_Length < T_Length) return 0; int i = 0, j = 0; int* next = new int[T_Length]; get_next(T, next); while(i < S_Length && j < T_Length){ if(j == -1 || *(S+i) == *(T+j)){ i++; j++; } else j=*(next+j); } if(j>=T_Length) return i-T_Length; return 0; } 在此提供一個更簡明的適用於字元串的kmp實現: #include<iostream> #include<string.h> int next[100]; void getnext(char b[]) { int i=1,j=0; //i是每個位子,j是回退的位子 next[1]=0; while(i<=strlen(b)) { if(j==0||b[i-1]==b[j-1]) { i++; j++; next[i]=j; } else j=next[j]; //用上一個的 回退關系 } } int kmp(char a[],char b[]) { int i=1,j=1; //i是主串中的位子 ,j匹配串的位子 while(i<=strlen(a)&&j<=strlen(b)) { if(j==0||a[i-1]==b[j-1]) { i++; j++; } else j=next[j]; } if(j>strlen(b)) return i-strlen(b); else return 0; } int main() { char a[40],b[40]; printf("要匹配的主串:\n"); scanf("%s",a); printf("要匹配的子串:\n"); scanf("%s",b); getnext(b); printf("輸出next值:\n"); for(int i=1;i<=strlen(b);i++) printf("%d ",next[i]); printf("\n"); printf("%d",kmp(a,b)); system("pause"); main(); return 0; }
編輯本段串的最大匹配演算法
摘要:
給定兩個串S和T,長分別m和n,本文給出了一個找出二串間最大匹配的演算法。該演算法可用於比較兩個串S和T的相似程度,它與串的模式匹配有別。
關鍵詞:
模式匹配 串的最大匹配 演算法 Algorithm on Maximal Matching of Strings Lin YuCai Xiang YongHong Zhang ChunXia Zhang JianJun (Computer Science Department of Yunnan Normal University Kunming 650092) ABSTRACT Given Two Strings S of length m and T of length n,the paper presents an algorithm which finds the maximal matching of them. The algorithm can be used to compare the similarility of the two strings S and T, it is different with the strings' pattren matching. KEY WORDS Pattern Matching Maximal Matching of Strings Algorithm
編輯本段問題的提出
字元串的模式匹配主要用於文本處理,例如文本編輯。文本數據的存儲(文本壓縮)和數據檢索系統。所謂字元串的模式匹配[2],就是給定兩個字元串S和T,長度分別為m和n,找出T中出現的一個或多個或所有的S,在這方面已經取得了不少進展[3][4][5][6][7][8][9][10][11]。本文從文本處理的另一個角度出發,找出兩個串的最大匹配,比較其相似程度[1]。它主要應用於文本比較,特別是在計算機輔助教學中。顯然前者要找S的完全匹配,而後者並無此要求。例如,若S=ABCD,T=EFABCDX,那麼模式匹配的結果就是找出了T中的一個ABCD,而我們演算法的結果就是S能與T的ABCD完全匹配,但是T中還有3個字元是比S多出來的,也就是說在S中有100%的字元與T中的匹配,而在T中有57%的字元與S中的匹配。若S= ABCDFE,T=AFXBECDY。則在模式匹配中S與T無匹配項,但在我們的演算法中就能發現T中存在A,B,C,D,但D後不存在E,F。而且S中也存在A,B,C,D,且具有順序性。這樣就能公正地評價S,T的區別。得知其相似程度。 文章的組織如下:首先介紹基本定義和問題的描述;第三節是演算法設計;最後是本文總結。
編輯本段問題的描述
設∑為任意有限集,其元稱為字元,w:∑→N為∑到N的函數,稱為∑的權函數(註:本文僅討論權值恆為1的情況)。∑*為∑上的有限字元串集合,那麼對任意S,T∈∑*,設S=a1a2…am,T=b1b2…bn,m>0,n>0。記<m>={1,2, …,m},<n>={1,2, …,n},則稱{(i,j)∣i∈<m>,j∈<n>,ai=bj}為S與T的匹配關系集,記作M(S,T),稱M為S與T的一個(容許)匹配,若對任意(i,j), ( i',j' )∈,① i< i',當且僅當j< j',② i= i'當且僅當j= j'。S與T的匹配中滿足 最大者,稱為S與T的最大匹配。若C(i,j)為N上的m×n矩陣,且滿足: 則稱矩陣C為串S與T的匹配關系陣。 於是求串S與T的最大匹配,等價於求C中的一個最大獨立點集M,它滿足,若ci,j,ci',j'∈M,則i< i' 當且僅當j< j',i=i'當且僅當j=j'。我們稱這樣的最大獨立點集為C的最大C-獨立點集。 例:設∑為所有字母的集合,對任意x∈∑,w(x)≡1,設S與T分別為:S=「BOOKNEWS」,T=「NEWBOOKS」。則我們可以得到S與T兩個匹配: 這里=5; 這里 =4。 顯然為串S與T的最大匹配。 S與T的匹配關系陣C可表示如下: 其中帶圈的部分為一最大C-獨立點集。
編輯本段演算法設計
我們僅就權值為一的情況進行討論。 設S和T為任意給定串,C為的S與T匹配關系陣,那麼由2的討論知,求S與T的最大匹配問題,等價於求C的最大C-獨立點集問題。因而,為了解決我們的問題,只要給出求C的最大C-獨立點集的演算法就可以了。 顯然,為了求出C的最大C-獨立點集,我們可以採用這樣的方法:搜索C的所有C-獨立點集,並找出它的最大者。這種方法是可行的,但並不是非常有效的。這會使問題變得很繁,復雜度很大。因此,我們先對問題進行分析。 在下面的討論中,我們把C的任一C-獨立點集={ai1,j1,…,ais,js},記作=ai1,j1…ais,js,i1 <…< is。於是可看作陣C中以1為節點的一條路,滿足:對路中的任意兩節點,均有某一節點位於另一節點的右下方。稱這種路為右下行路。 於是求C-獨立點集等價於求陣C的右下行路。這種求右下行路的搜索可以逐行往下進行。 命題1. 若 =αai,jβ和ψ=α'ai,jσ為C的兩個C-獨立點集,且α為α'的加細,則存在C-獨立點集'=αai,jδ,滿足≥。 命題2. 若 =αai,jβ和ψ=α'ai+k,jσ為C的兩個C-獨立點集,且≥,則存在C-獨立點集'=αai,jδ,滿足≥。 命題3. 若 =αai,jβ和ψ=α'ai,j+kσ為C的兩個C-獨立點集,且≥,則存在C-獨立點集'=αai,jδ,滿足≥。 由命題1知,在搜索右下行路的過程中,如果已獲得了某一C-獨立點集的某一初始截段αai,j和另一C-獨立點集ψ的某一初始截段α'ai,j,且有≤,則我們可以停止對ψ的進一步搜索。 由命題2知,在搜索右下行路的過程中,在某一列j存在某兩個C-獨立點集的某初始截段=ai1,j1…ais,j和ψ=al1,m1…alt,j,如果≥,但lt>is,則我們可以停止對ψ的進一步搜索。 由命題3知,在搜索右下行路的過程中,在某一行i存在某兩個C-獨立點集的某初始截段=ai1,j1…ai,js和ψ=ai1,m1…ai,mt,如果≥,但mt>js,則我們可以停止對ψ的進一步搜索。 由此可見,並不要求搜索所有C的最大C-獨立點集,而可以採用比這簡單得多的方法進行計算。那麼按照我們上面的三個命題,來看如下實例: 首先我們得到=B(在上的節點用①表示),我們向右下方找路,可以發現,在第4列有兩個1,根據命題2,我們選擇上面的一個1,也就是說選擇第1行的那個1,而不要第2行的那個1。同時我們也發現在第1行也有兩個1,由命題3知,我們選擇左邊的那個1,即第4列的那個1。此時=BO。但是當我們的演算法運行到第4行時,=BOOK,由於K在第3行第6列,而本行的1在第1列,在路最後一個節點K的左邊,那麼我們必須新建一條路ψ,因為我們並不能確定是否以後就有≥,當演算法運行到第6行時,=BOOK,ψ=NEW,=4,=3,我們將S鏈到路上,此時我們得到最長右下行路=BOOKS,=5。這樣我們就可以計算出這兩個字元串的匹配程度。 在我們的演算法設計過程中,用到了兩個技巧。技巧之一,矩陣C不用存儲,是動態建立的,節省了空間。技巧之二,本演算法並不要求所有的S與T中所有的元素都相互進行比較,也並不存儲所有的右下行路,節省了時間和空間。由矩陣中1的出現情況可見,本演算法所需的空間和時間都遠小於O(mn)
編輯本段結束語
本文給出了一個與模式匹配不同的,具有若干應用的,串的最大匹配演算法,該演算法已經在機器上實現,達到了預期的效果。本文僅討論權值恆為1的情況,對於權值任意的情形不難由此得到推廣。
編輯本段C語言代碼(C Code)
#include<stdio.h> #include<string.h> void getnext(int next[],char s[],int l) { int i=1,j=0; next[1]=0; while(i<l) { if(j==0 || s[i]==s[j]) { i++;j++; next[i]=j; } else j=next[j]; } } int KMP(char s1[],char s2[],int l1,int l2,int next[]) { int i,j; i=j=1; while(i<=l1 && j<=l2) { if(j==0||s1[i]==s2[j]) { i++;j++; } else j=next[j]; } if(j>l2) return(i-l2); return 0; } int main() { int next[10001],ans; char s1[10001],s2[10001],l1,l2; scanf("%s",s1+1); scanf("%s",s2+1); l1=strlen(s1+1); l2=strlen(s2+1); getnext(next,s2,l2); ans=KMP(s1,s2,l1,l2,next); if(ans!=0) printf("%d\n",ans); else printf("No!\n"); system("pause"); return 0; }
編輯本段KMP演算法的pascal實現
var next:array [1 ..1000001] of longint; s,t:ansistring; procere get_next(t:ansistring); var j,k:integer; begin j:=1; k:=0; while j<length(t) do begin if (k=0) or (t[j]=t[k]) then begin inc(j); inc(k); next[j]:=k; end else k:=next[k]; end; end; function index(s:ansistring;t:ansistring):longint; var i,j:longint; begin get_next(t); index:=0; i:=1; j:=1; while (i<=length(s))and(j<=length(t)) do begin if (j=0)or(s[i]=t[j]) then begin inc(i); inc(j); end else j:=next[j]; if j>length(t) then index:=i-length(t); end; end; begin readln(s); readln(t); writeln(index(s,t)) end.
編輯本段KMP播放器
K-multimedia player的縮寫
來自韓國的影音全能播放器,與Mplayer一樣從linux平台移植而來的Kmplayer(簡稱KMP)幾乎可以播放您系統上所有的影音文件。通過各種插件擴展KMP可以支持層出不窮的新格式。強大的插件功能,直接從Winamp繼承的插件功能,能夠直接使用winamp的音頻 ,輸入,視覺效果插件,而通過獨有的擴展能力,只要你喜歡,可以選擇使用不同解碼器對各種格式進行解碼。 KMPlayer The Professional Media Player! 它支持 Winamp 2/5 的輸入、常規、DSP、視覺效果、媒體庫插件。無須注冊表支持直接調用 Directshow 濾鏡!FFdshow 的視覺特效系統~超強的 GUI 界面~安裝電視卡後可以直接代替原軟體直接收看電視~支持播放 DVD/VCD 以及絕大多數電腦的媒體文件(AVI 支持 Xvid/DivX/3vid/H264 OGG/OGM/MKV 容器/AC3/DTS 解碼~Monkey Audio 解碼~)強烈推薦!此播放器除了會將自己的配置信息寫入注冊表外絕對綠色~ KMplayer內置目前常見的所有解碼器,包括real,QT等。 另外KMplayer安裝版也是目前很少見的檢查流氓軟體的安裝方式,如果一旦有惡意的漢化小組漢化並捆綁了流氓軟體。該安裝程序自動會識別,並作出提示,建議用戶不要安裝,雖然不是特別准確,但KMplayer的無廣告及第三方插件的特點使其深受好評。 目前韓國官方已經在Kmplayer里自帶了中文字型檔,只要用戶是中文系統,軟體就會自動識別,十分方便。 KMP版本: KMPlayer3.0.0.1439

Ⅱ 數據結構中的KMP演算法怎樣用C實現

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define MAX_LEN_OF_STR 30 // 字元串的最大長度
typedef struct String // 這里需要的字元串數組,存放字元串及其長度{
char str[MAX_LEN_OF_STR]; // 字元數組
int length;// 字元串的實際長度
}String, *PString;
// 得到字元串的next數組
void GetNextArray(PString pstr, int next[])
{assert(NULL != pstr); <br/>assert(NULL != next);<br/>assert(pstr->length > 0);// 第一個字元的next值是-1,因為C中的數組是從0開始的<br/>next[0] = -1;<br/>for (int i = 0, j = -1; i < pstr->length - 1; )<br/>{// i是主串的游標,j是模式串的游標// 這里的主串和模式串都是同一個字元串<br/> if (-1 == j || // 如果模式串游標已經回退到第一個字元<br/>pstr->str[i] == pstr->str[j]) // 如果匹配成功<br/> {// 兩個游標都向前走一步<br/> ++i;++j;// 存放當前的next值為此時模式串的游標值<br/> next[i] = j;<br/> }else // 匹配不成功j就回退到上一個next值
{j = next[j];}}}
// KMP字元串模式匹配演算法
// 輸入: S是主串,T是模式串,pos是S中的起始位置
// 輸出: 如果匹配成功返回起始位置,否則返回-1
int KMP(PString S, PString T, int pos)
{assert(NULL != S);<br/> assert(NULL != T);<br/> assert(pos >= 0);<br/> assert(pos < S->length);<br/>if (S->length < T->length)<br/> return -1;<br/>printf("主串\t = %s\n", S->str);<br/>printf("模式串\t = %s\n", T->str);<br/>int *next = (int *)malloc(T->length * sizeof(int));// 得到模式串的next數組<br/>GetNextArray(T, next);<br/>int i, j;<br/>for (i = pos, j = 0; i < S->length && j < T->length; ){// i是主串游標,j是模式串游標<br/> if (-1 == j || // 模式串游標已經回退到第一個位置<br/> S->str[i] == T->str[j]) // 當前字元匹配成功<br/> {// 滿足以上兩種情況時兩個游標都要向前進一步<br/> ++i;++j;}
else // 匹配不成功,模式串游標回退到當前字元的next值
{j = next[j];}}
free(next);
if (j >= T->length)
{// 匹配成功
return i - T->length;}
else{// 匹配不成功
return -1;}}

Ⅲ KMP模式匹配演算法是什麼

KMP模式匹配演算法是一種改進演算法,是由D.E.Knuth、J.H.Morris和v.R.Pratt提出來的,因此人們稱它為「克努特-莫里斯-普拉特操作」,簡稱KMP演算法。此演算法可以在O(n+m)的時間數量級上完成串的模式匹配操作。其改進在於:每當一趟匹配過程出現字元不相等時,主串指針i不用回溯,而是利用已經得到的「部分匹配」結果,將模式串的指針j向右「滑動」盡可能遠的一段距離後,繼續進行比較。

1.KMP模式匹配演算法分析回顧圖4-5所示的匹配過程示例,在第三趟匹配中,當i=7、j=5字元比較不等時,又從i=4、j=1重新開始比較。然而,經仔細觀察發現,i=4和j=1、i=5和j=1以及i=6和j=1這三次比較都是不必進行的。因為從第三趟部分匹配的結果就可得出,主串中的第4、5和6個字元必然是b、c和a(即模式串第2、第2和第4個字元)。因為模式中的第一個字元是a,因此它無須再和這三個字元進行比較,而僅需將模式向右滑動2個字元的位置進行i=7、j=2時的字元比較即可。同理,在第一趟匹配中出現字元不等時,僅需將模式串向右移動兩個字元的位置繼續進行i=2、j=1時的字元比較。由此,在整個匹配過程中,i指針沒有回溯,如圖1所示。

圖1改進演算法的模式匹配過程示意

Ⅳ 數據結構里實現KMP演算法

KMP演算法的C語言實現2007-12-10 23:33

基本思想:
這種演算法是D.E.Knuth 與V.R.Pratt和J.H.Morris同時發現的,因此人們稱為KMP演算法。此演算法可以在O(n+m)的時間數量級上完成串的模式匹配操作。
其基本思想是:每當匹配過程中出現字元串比較不等時,不需回溯i指針,而是利用已經得到的「部分匹配」結果將模式向右「滑動」盡可能遠的一段距離後,繼續進行比較。

#include <stdio.h>
#include <string.h>
int index_KMP(char *s,char *t,int pos);
void get_next(char *t,int *);

char s[10]="abcacbcba";
char t[4]="bca";
int next[4];
int pos=0;

int main()
{
int n;
get_next(t,next);
n=index_KMP(s,t,pos);
printf("%d",n);
return 0;
}

int index_KMP(char *s,char *t,int pos)
{
int i=pos,j=1;
while (i<=(int)strlen(s)&&j<=(int)strlen(t))
{
if (j==0||s[i]==t[j-1])
{
i++;
j++;
}
else j=next[j];
}
if (j>(int)strlen(t))
return i-strlen(t)+1;
else
return 0;
}

void get_next(char *t,int *next)
{

int i=1,j=0;
next[0]=next[1]=0;
while (i<(int)strlen(t))
{
if (j==0||t[i]==t[j])
{
i++;
j++;
next[i]=j;
}
else j=next[j];
}

}

Ⅳ KMP演算法的原理及其應用

KMP演算法是通過分析子串,預先計算每個位置發生不匹配的時候,所需GOTO的下一個比較位置,整理出來一個next數組,然後再上面的演算法中使用。
講解一下:
當我們分析一個子串時,例如:abcabcddes. 需要分析一下,每個字元x前面最多有多少個連續的字元和字元串從初始位置開始的字元匹配。然後+1就行了(別忘了,我們的字元串都是從索引1開始的)當然,不要相同位置自己匹配,默認第一個字元的匹配數是0。
定義如下:設字元串為 x1x2x3...xn ,其中x1,x2,x3,... xi,... xn均是字元,設ai為字元xi對應的整數。則a=m,當且僅當滿足如下條件:字元串x1x2...xm equals 字元串x(i-m+1)...xi-1 xi 並且x1x2...xm x(m+1) unequals x(i-m) x(i-m+1)...xi-1 xi。
舉例如下:
abcabcddes
0111234111
|----------------------默認是0
--| | |-----------------不能自己相同字元匹配,所以這里者能認為是沒有所以是0+1 =1
------| | |-----------前面的字元和開始位置的字元相同,所以是2,3,4
-----------| | | |-------不匹配只能取1。
希望能明白的是,如果開始字元是 Ch1的話,那麼我們就是要在串中第2個Ch1後面的位置開始自己和自己匹配,計算最大的吻合度。
程序寫出來就是:
void GetNext(char* T, int *next)
{
int k=1,j=0;
next[1]=0;
while( k〈 T[0] ){
if (j ==0 || T[k] == T[j])
{
++k;
++j;
next[k] = j;
}
else j= next[j];
}
}
但是這個不是最優的,因為他沒有考慮aaaaaaaaaaaaaaaaaaab的情況,這樣前面會出現大量的1,這樣的演算法復雜度已經和最初的樸素演算法沒有區別了。所以稍微改動一下:
void GetNextEx(char *T, char *next)
{
int i=k,j=0; next[1] = 0;
while(k < T[0])
{
if (j == 0 || T[k] == T[j])
{
++k; ++j;
if (T[k] == T[j])
next[k] = next[j];
else
next[k] = j;
}
else j = next[j];
}
}
現在我們已經可以得到這個next字元串的值了,接下來就是KMP演算法的本體了:
相當簡單:
int KMP(char* S, char* T, int pos)
{
int k=pos, j=1;
while (k){
if (S[k] == T[j]){ ++k; ++j; }
else j = next[j]
}
if (j>T[0]) return k-T[0];
else return 0;
}
和樸素演算法相比,只是修改一句話而已,但是演算法復雜度從O(m*n) 變成了:O(m)

Ⅵ !!編譯原理DFA和NFA

DFA或NFA是對計算機程序的行為的抽象模型。你編寫的程序其實就對應了一個自動機。簡單舉例來說,如果a,b可以取值0或1; 程序: if(a==1) b=1; 這個程序對應了一個自動機。
對應的自動機就有狀態 (0,0), (0,1), (1,1), (1, 0)
比如你自動機的初始狀態是 (1,0)即a=1,b=0時,運行程序的下一個狀態就是(1,1)。

畫圖出來就是 這4個狀態作為頂點,並且有下面幾條邊
(0,0) --> (0,0)(自環), (1,0)-->(1,1), (1,1)-->(1,1)(自環), (0,1)-->(0,1)自環

存在的意義就是一種理論模型,也可以認為是一種編程思想。 詞法分析系也離不開 if else, 這一系列的if else和條件也就組成自動機。。。

最經典體現自動機思想的演算法就是KMP演算法,你肯定學過,字元串子串匹配的演算法。 回憶這個演算法的過程:演算法第一步構造的next表(數據結構教材的說法)其實就是根據子串的內容構造了一個自動機! 演算法第二步將原串作為自動機輸入,自動機的輸出就是匹配到的子串位置或者無匹配。

Ⅶ KMP演算法

演算法3.5——KMP演算法
1. 在串S和串T中分別設比較的起始下標i和j;
2. 循環直到S中所剩字元長度小於T的長度或T中所有字元均比較完畢
2.1 如果S[i]=T[j],則繼續比較S和T的下一個字元;否則
2.2 將j向右滑動到next[j]位置,即j=next[j];
2.3 如果j=0,則將i和j分別加1,准備下一趟比較;
3. 如果T中所有字元均比較完畢,則返回匹配的起始下標;否則返回0;
void GetNext(char T[ ], int next[ ])
{
next[1]=0;
j=1; k=0;
while (j<T[0])
if ((k= =0)| |(T[j]= =T[k])) {
j++;
k++;
next[j]=k;
}
else k=next[k];
}

Ⅷ KMP演算法詳細代碼

KMP.java

源代碼為:

package algorithm.kmp;

/**
* KMP演算法的Java實現例子與測試、分析
* @author 崔衛兵
* @date 2009-3-25
*/
public class KMP {
/**
* 對子串加以預處理,從而找到匹配失敗時子串回退的位置
* 找到匹配失敗時的最合適的回退位置,而不是回退到子串的第一個字元,即可提高查找的效率
* 因此為了找到這個合適的位置,先對子串預處理,從而得到一個回退位置的數組
* @param B,待查找子串的char數組
* @return
*/
public static int[] preProcess(char [] B) {
int size = B.length;
int[] P = new int[size];
P[0]=0;
int j=0;
//每循環一次,就會找到一個回退位置
for(int i=1;i<size;i++){
//當找到第一個匹配的字元時,即j>0時才會執行這個循環
//或者說p2中的j++會在p1之前執行(限於第一次執行的條件下)
//p1
while(j>0 && B[j]!=B[i]){
j=P[j];
}
//p2,由此可以看出,只有當子串中含有重復字元時,回退的位置才會被優化
if(B[j]==B[i]){
j++;
}
//找到一個回退位置j,把其放入P[i]中
P[i]=j;
}
return P;
}

/**
* KMP實現
* @param parStr
* @param subStr
* @return
*/
public static void kmp(String parStr, String subStr) {
int subSize = subStr.length();
int parSize = parStr.length();
char[] B = subStr.toCharArray();
char[] A = parStr.toCharArray();
int[] P = preProcess(B);
int j=0;
int k =0;
for(int i=0;i<parSize;i++){
//當找到第一個匹配的字元時,即j>0時才會執行這個循環
//或者說p2中的j++會在p1之前執行(限於第一次執行的條件下)
//p1
while(j>0 && B[j]!=A[i]){
//找到合適的回退位置
j=P[j-1];
}
//p2 找到一個匹配的字元
if(B[j]==A[i]){
j++;
}
//輸出匹配結果,並且讓比較繼續下去
if(j==subSize){
j=P[j-1];
k++;
System.out.printf("Find subString '%s' at %d\n",subStr,i-subSize+1);
}
}
System.out.printf("Totally found %d times for '%s'.\n\n",k,subStr);
}

public static void main(String[] args) {
//回退位置數組為P[0, 0, 0, 0, 0, 0]
kmp("abcdeg, abcdeh, abcdef!這個會匹配1次","abcdef");
//回退位置數組為P[0, 0, 1, 2, 3, 4]
kmp("Test ititi ititit! Test ititit!這個會匹配2次","ititit");
//回退位置數組為P[0, 0, 0]
kmp("測試漢字的匹配,崔衛兵。這個會匹配1次","崔衛兵");
//回退位置數組為P[0, 0, 0, 1, 2, 3, 4, 5, 6]
kmp("這個會匹配0次","it1it1it1");
}
}

Ⅸ 求kmp演算法的詳細解釋。(最好附上能運行的程序)

t;i),那麼next[i]就是所有這樣的j的最大值
形象地說,就是假如第i 1個字元匹配失敗之後,下一個可能匹配位置至少應該往後挪動多少

就"abaabc"而言
next[1]=0
next[2]=0
next[3]=1
next[4]=1
next[5]=2
next[6]=0

計算過程基本上抄自演算法導論,假設str長度為n
k=0;//k表示當前匹配了多少位
next[1]=0;
for (i=1;in;i )
{
while (k

Ⅹ 什麼是KMP演算法

KMP就是串匹配演算法
運用自動機原理
比如說
我們在S中找P
設P={ababbaaba}
我們將P對自己匹配
下面是求的過程:{依次記下匹配失敗的那一位}
[2]ababbaaba
......ababbaaba[1]
[3]ababbaaba
........ababbaaba[1]
[4]ababbaaba
........ababbaaba[2]
[5]ababbaaba
........ababbaaba[3]
[6]ababbaaba
..............ababbaaba[1]
[7]ababbaaba
..............ababbaaba[2]
[8]ababbaaba
.................ababbaaba[2]
[9]ababbaaba
.................ababbaaba[3]
得到Next數組『0,1,1,2,3,1,2,2,3』
主過程:
[1]i:=1 j:=1
[2]若(j>m)或(i>n)轉[4]否則轉[3]
[3]若j=0或a[i]=b[j]則【inc(i)inc(j)轉[2]】否則【j:=next[j]轉2】
[4]若j>m則return(i-m)否則return -1;
若返回-1表示失敗,否則表示在i-m處成功
若還不懂mail:[email protected]

參考一下這里吧:

http://www.chinaaspx.com/archive/delphi/4733.htm

閱讀全文

與dfa實現kmp演算法相關的資料

熱點內容
70個4相乘的簡便演算法 瀏覽:291
安卓手機沒有機身存儲了怎麼辦 瀏覽:314
輸入法文件夾不能用 瀏覽:83
發單買多大的雲伺服器 瀏覽:331
特價雲伺服器如何注冊 瀏覽:296
安卓手機賬戶忘記密碼怎麼解鎖 瀏覽:821
如何用健身app確定一個特工 瀏覽:911
多級壓縮的原理 瀏覽:864
java項目開發案例視頻 瀏覽:70
文件夾快速查找表格不同內容 瀏覽:493
合並排序演算法java 瀏覽:920
如何將文件夾刪除的部分恢復 瀏覽:808
eco為什麼連接不上伺服器 瀏覽:294
查看linux的命令是 瀏覽:12
蘋果郵件伺服器地址 瀏覽:343
U盤超級加密3000時間 瀏覽:738
如何跟別人解釋什麼是伺服器 瀏覽:939
安卓11原生如何隱藏軟體 瀏覽:712
解壓清潔面部女士 瀏覽:856
美的變頻空調壓縮啟動一下報p1 瀏覽:472