php實現kmp算法,kmp算法詳解

本文目錄一覽:

KMP算法,輸三組主串S和模式串P,輸出模式串的Next(j)函數值,及該P在S中的位置的定

KMP算法查找串S中含串P的個數count

#include iostream

#include stdlib.h

#include vector

using namespace std;

inline void NEXT(const string T,vectorint next)

{

//按模式串生成vector,next(T.size())

next[0]=-1;

for(int i=1;iT.size();i++ ){

int j=next[i-1];

while(T[i]!=T[j+1] j=0 )

j=next[j] ; //遞推計算

if(T[i]==T[j+1])next[i]=j+1;

else next[i]=0; //

}

}

inline string::size_typeCOUNT_KMP(const string S,

const string T)

{

//利用模式串T的next函數求T在主串S中的個數count的KMP算法

//其中T非空,

vectorint next(T.size());

NEXT(T,next);

string::size_type index,count=0;

for(index=0;indexS.size();++index){

int pos=0;

string::size_type iter=index;

while(posT.size() iterS.size()){

if(S[iter]==T[pos]){

++iter;++pos;

}

else{

if(pos==0)++iter;

else pos=next[pos-1]+1;

}

}//while end

if(pos==T.size()(iter-index)==T.size())++count;

} //for end

return count;

}

int main(int argc, char *argv[])

{

string S=”abaabcacabaabcacabaabcacabaabcacabaabcac”;

string T=”ab”;

string::size_type count=COUNT_KMP(S,T);

coutcountendl;

system(“PAUSE”);

return 0;

}

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算法是通過分析子串,預先計算每個位置發生不匹配的時候,所需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 (jT[0]) return k-T[0];

else return 0;

}

和樸素算法相比,只是修改一句話而已,但是算法複雜度從O(m*n) 變成了:O(m)

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;isize;i++){

//當找到第一個匹配的字符時,即j0時才會執行這個循環

//或者說p2中的j++會在p1之前執行(限於第一次執行的條件下)

//p1

while(j0 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;iparSize;i++){

//當找到第一個匹配的字符時,即j0時才會執行這個循環

//或者說p2中的j++會在p1之前執行(限於第一次執行的條件下)

//p1

while(j0 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算法詳解

KMP模式匹配算法

KMP算法是一種改進的字符串匹配算法,其關鍵是利用匹配失敗後的信息,盡量減少模式串與主串的匹配次數以達到快速匹配的目的明[4]。

求得模式的特徵向量之後,基於特徵分析的快速模式匹配算法(KMP模式匹配算法)與樸素匹配算法類似,只是在每次匹配過程中發生某次失配時,不再單純地把模式後移一位,而是根據當前字符的特徵數來決定模式右移的位數[3]。

include “string. h”

#includeassert. h

int KMPStrMatching(String T, String P, int. N, int startIndex)

{int lastIndex=T.strlen() -P.strlen();

if((1 astIndex- startIndex)0)//若 startIndex過大,則無法匹配成功

return (-1);//指向P內部字符的游標

int i;//指向T內部字符的游標

int j=0;//指向P內部字符的游標

for(i= startIndex; i T.strlen(); i++)

{while(P[j]!=T[i] j0)

j=N[j-1];

if(P[j]==T[i])

j++;

if(j ==P.strlen())

return(1-j+1);//匹配成功,返回該T子串的開始位置

}

return (-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];

}

}

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/238770.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 12:13
下一篇 2024-12-12 12:13

相關推薦

  • 蝴蝶優化算法Python版

    蝴蝶優化算法是一種基於仿生學的優化算法,模仿自然界中的蝴蝶進行搜索。它可以應用於多個領域的優化問題,包括數學優化、工程問題、機器學習等。本文將從多個方面對蝴蝶優化算法Python版…

    編程 2025-04-29
  • PHP和Python哪個好找工作?

    PHP和Python都是非常流行的編程語言,它們被廣泛應用於不同領域的開發中。但是,在考慮擇業方向的時候,很多人都會有一個問題:PHP和Python哪個好找工作?這篇文章將從多個方…

    編程 2025-04-29
  • Python實現爬樓梯算法

    本文介紹使用Python實現爬樓梯算法,該算法用於計算一個人爬n級樓梯有多少種不同的方法。 有一樓梯,小明可以一次走一步、兩步或三步。請問小明爬上第 n 級樓梯有多少種不同的爬樓梯…

    編程 2025-04-29
  • AES加密解密算法的C語言實現

    AES(Advanced Encryption Standard)是一種對稱加密算法,可用於對數據進行加密和解密。在本篇文章中,我們將介紹C語言中如何實現AES算法,並對實現過程進…

    編程 2025-04-29
  • Harris角點檢測算法原理與實現

    本文將從多個方面對Harris角點檢測算法進行詳細的闡述,包括算法原理、實現步驟、代碼實現等。 一、Harris角點檢測算法原理 Harris角點檢測算法是一種經典的計算機視覺算法…

    編程 2025-04-29
  • 數據結構與算法基礎青島大學PPT解析

    本文將從多個方面對數據結構與算法基礎青島大學PPT進行詳細的闡述,包括數據類型、集合類型、排序算法、字符串匹配和動態規劃等內容。通過對這些內容的解析,讀者可以更好地了解數據結構與算…

    編程 2025-04-29
  • 瘦臉算法 Python 原理與實現

    本文將從多個方面詳細闡述瘦臉算法 Python 實現的原理和方法,包括該算法的意義、流程、代碼實現、優化等內容。 一、算法意義 隨着科技的發展,瘦臉算法已經成為了人們修圖中不可缺少…

    編程 2025-04-29
  • PHP怎麼接幣

    想要在自己的網站或應用中接受比特幣等加密貨幣的支付,就需要對該加密貨幣擁有一定的了解,並使用對應的API進行開發。本文將從多個方面詳細闡述如何使用PHP接受加密貨幣的支付。 一、環…

    編程 2025-04-29
  • 神經網絡BP算法原理

    本文將從多個方面對神經網絡BP算法原理進行詳細闡述,並給出完整的代碼示例。 一、BP算法簡介 BP算法是一種常用的神經網絡訓練算法,其全稱為反向傳播算法。BP算法的基本思想是通過正…

    編程 2025-04-29
  • 粒子群算法Python的介紹和實現

    本文將介紹粒子群算法的原理和Python實現方法,將從以下幾個方面進行詳細闡述。 一、粒子群算法的原理 粒子群算法(Particle Swarm Optimization, PSO…

    編程 2025-04-29

發表回復

登錄後才能評論