KMP 演算法,search 子串

2021-05-25 08:36:52 字數 3610 閱讀 1466

網上看了好多關於kmp演算法的,但是都是看的不清不楚的,用了好多術語,不明白,後來自己根據結果倒推了過程,不知對不對,

暫時先記下來,

kmp演算法,需要預先處理子串,然後建立乙個int型別next陣列(名字無所謂,主要是儲存一些關於子串的資訊),這裡有幾點要注意:

next陣列計算方法(假定j為數字下標,j >= 1)

j = 1時, next[j] = 0, 這個是必定的,所有的next子串模式陣列next[1] 都是0, next[0]這個棄之不用,

當然只是在下標的範圍上不用,實際的陣列空間我們還是要用的,也就是說,我們演算法中的j值於實際的下標之間有

下標 = j - 1

的換算關係。

j = 2時, next[j] = 1, 這個也是定死的,但仍你按後邊的公式也可以推出這個的值,

j > 2時,   next[j] 的值為

j位置前緊鄰的字串與子串第乙個字元開始最大的相同子串數+1。這句是我從網上copy 來的,看不懂,但是我覺著應該是這樣的:

j位置前緊鄰的字元與子串第乙個字元開始最大的相同字元數+1,

我們舉個例子說明:

比如有子串: abaabcac,  它的next模式陣列應該是0,1,1,2,2,3,1,2, 我們來看下是怎樣得來的,

第一位是0,第二位是1,這是定死的,所以有0,1,

我們看第三位,第三位對應的字元是a,注意我們的下標從1,開始:

abaabcac

他前邊的字元是b,b對應的next值是1,所以,我們從子串的乙個字元開始比較,

因為子串第乙個字元是a,所以b沒有相同的字元,則next[3] = 0 + 1,

我們看第四位,對應的字元是a,

abaabcac

它前邊的字元是a,並且next[3] = 1, 所以我們從子串的第一位開始比較, a == a, 所有有乙個字元相同,所有next[4] = 1 + 1,

我們看第五位,對應的字元是b,

abaabcac

他前邊的字元是a,對應的next[4] = 2, 所以從第二位開始比較,a != b, 不同,要向前與第一位比較,a == a, 有乙個字元相同,所有

next[5] = 1 + 1, 其實這裡可以取得前乙個字元的next值,

n = next[j - 1],  此處 n = 2, 然後在比較指標向前移動時,n 相應 - 1, 比如此處,在a != b是, 要與前一位比較

則n 要 -1,

我們看第六位,對應的字元是c,

abaabcac

他前邊的字元是b,對應的next[5] = 2, 所以從第二位開始比較,b == b, 所以, next[6] = next[5] + 1,

我們看第七位,對應的字元是a,,

abaabcac

他前邊的字元是c,對應的next[6] = 3, 所以從第三位開始比較,

定義 n = next[6] = 3

a != c,

所有要與第二位再次比較,同時n = n -1;

b != c,

與第一位比較,n = n -1,

a != c,

所以此位next[7] = 0 + 1

我們看第八位,對應的字元是c,

abaabcac

他前邊的字元是a,對應的next[7] = 1, 所以於第一位比較 a == a,

所以 next[ 8] = 1 + 1 = 2,

所以最終的next 數字序列是: 0,1,1,2,2,3,1,2

然後我們看比較過程,這裡就比較簡單了:

比較方法:

1.當s[i]=p[j],則:i++,j++;

2.當s[i]!=p[j],如果此時j!=0,則j=next[j],再繼續比較;

如果j=0 則i++,j++,再繼續比較

void

parsenextvector

(string

&substr

, vector

<

int> &

nextvec

)int

j= 1;

nextvec

.push_back

(0);

//pos 1; pos 0 never used.

j++;

nextvec

.push_back

(1);

// pos 2;

j++;

for(

inti

= 3;

i<=

substr

.length

();

i++)

intj=

i-1;

intx

= nextvec

.back

();while

(1)

cout

<<

substr[j

- 1] <<

" "<<

substr[x

- 1] <<

endl;if

(substr[j

-1] ==

substr[x

- 1])

nextvec

.push_back(x

+ 1);

break;

else x

--;if(x

== 0)

nextvec

.push_back

(1);

break;

intkmpsearch

(string

& str

, string

& substr

, vector

<

int>&

nextvec)

intj

= 0;

inti

= 0;

while(i

<

str.

length

())

cout

<<

str[

i] <<

" "<<

substr[j

] <<

endl;if

(str[i

] ==

substr[j

]) if(

j==

substr

.length

() - 1)

cout

<<

i<<

" "<<

j<<

endl

;return(i

- j);

j++;

i++;

else

j= nextvec[j

];j= j

- 1;if(

j< -1)

cout

<<

"error: "

<<

j<<

endl

;return

-1;}

elseif(

j== -1) j

++;i

++;

return

-1;

這裡的比較**很簡單,我沒仔細看,

KMP 子串查詢演算法

如何在目標字串s中,查詢是否存在子串p?樸素解法 字串s中查詢子串p的位置 int sub str index const char s,const char p ret equal i 1 return ret 樸素解法的乙個優化線索 因為,pa pb pc 且 pc sc 所以,pa sb pa...

刪除子串 KMP

題目描述 輸入的第一行是字串 s 第二行是字串 t 輸出格式 輸出最後的 s 串。資料保證 s 串不會為空串。樣例輸入 whatthemomooofun moo 樣例輸出 whatthefun 樣例說明 當列舉到 whatthemomoo 時,刪除 moo 得到 whatthemo 繼續列舉 o 得...

串 KMP演算法

一 串 1 串是由 0個或者多個字元構成的有限序列 2 字典序 定義字串的大小也稱為字典序。1 若兩個串長度為 m,n。m n,則m 串大於n串 2 若m n 當兩串,第乙個不同的字元,哪個大的哪個串就大 二 串的儲存 1 順序儲存 定長儲存串,放在陣列中進行操作。當溢位了後會自動截斷 2 堆分配儲...