網上看了好多關於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 堆分配儲...