不要用while(istrlen(p))與while(Istrlen(s)),這樣每進行一次循環(huán)就要重新計算串的長度,會把本身是O(n)的算法變O(n^2)的。t=strlen(s);while(it) { } 這樣子就行了
創(chuàng)新互聯(lián)建站-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比橋東網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式橋東網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務覆蓋橋東地區(qū)。費用合理售后完善,10年實體公司更值得信賴。
求next程序代碼:
void? getNext(char*p,int*next)
{? ?
int? ?j,k;? ?
next[0]=-1;?j=0;k=-1;? ?
while(jstrlen(p)-1)
{? ? ? ?
? if(k==-1||p[j]==p[k])? ? //匹配的情況下,p[j]==p[k]? ? ? ?
? {? ? ? ? ? ?
? ? ? ?j++;? ? ? ? ? ?
? ? ? ?k++;? ? ? ? ? ?
? ? ? ?next[j]=k;? ? ? ?
? }? ? ? ?
? else? ? ? ? ? //p[j]!=p[k]? ? ? ? ? ?
? ? ? k=next[k];? ?
}
}?
KMP算法主程序:
int? ?KMPMatch(char*s,?char*p)
{? ?
int? ? next[100];? ?
int? ? i,j;? i=0;? j=0;? ?
getNext(?p,?next?);? ?
while(?i??strlen(s)?){? ? ? ?
? if(j==-1||s[i]==p[j])? ? ? ?
? {? ? ? ? ? ?
? ? ? i++;? ? ? ? ? ?
? ? ? j++;? ? ? ?
? }
? else
? {? ? ? ? ? ?
? ? ? j=next[j];? ? ? ?//消除了指針i的回溯? ? ? ?
? }? ? ? ?
? if(j==strlen(p))? ? ? ? ? ?
? ? ? return? ? i-strlen(p);? ?
}? ?
return-1;
}?
kmp算法
一種改進的字符串匹配算法,由D.E.Knuth與V.R.Pratt和J.H.Morris同時發(fā)現(xiàn),因此人們稱它為克努特——莫里斯——普拉特操作(簡稱KMP算法)。
完全掌握KMP算法思想
學過數(shù)據(jù)結(jié)構(gòu)的人,都對KMP算法印象頗深。尤其是新手,更是難以理解其涵義,搞得一頭霧水。今天我們就來面對它,不將它徹底搞懂,誓不罷休。
如今,大伙基本上都用嚴蔚敏老師的書,那我就以此來講解KMP算法。(小弟正在備戰(zhàn)考研,為了節(jié)省時間,很多課本上的話我都在此省略了,以后一定補上。)
嚴老的《數(shù)據(jù)結(jié)構(gòu)》79頁講了基本的匹配方法,這是基礎(chǔ)。先把這個搞懂了。
80頁在講KMP算法的開始先舉了個例子,讓我們對KMP的基本思想有了最初的認識。目的在于指出“由此,在整個匹配的過程中,i指針沒有回溯,”。
我們繼續(xù)往下看:
現(xiàn)在討論一般情況。
假設(shè) 主串:s: ‘s(1) s(2) s(3) ……s(n)’ ; 模式串 :p: ‘p(1) p(2) p(3)…..p(m)’
把課本上的這一段看完后,繼續(xù)
現(xiàn)在我們假設(shè) 主串第i個字符與模式串的第j(j=m)個字符‘失配’后,主串第i個字符與模式串的第k(kj)個字符繼續(xù)比較
此時,s(i)≠p(j), 有
主串: S(1)…… s(i-j+1)…… s(i-1) s(i) ………….
|| (相配) || ≠(失配)
匹配串: P(1) ……. p(j-1) p(j)
由此,我們得到關(guān)系式
‘p(1) p(2) p(3)…..p(j-1)’ = ’ s(i-j+1)……s(i-1)’
由于s(i)≠p(j),接下來s(i)將與p(k)繼續(xù)比較,則模式串中的前(k-1)個字符的子串必須滿足下列關(guān)系式,并且不可能存在 k’k 滿足下列關(guān)系式:(kj),
‘p(1) p(2) p(3)…..p(k-1)’ = ’ s(i-k+1)s(i-k+2)……s(i-1)’
即:
主串: S(1)……s(i-k +1) s(i-k +2) ……s(i-1) s(i) ………….
|| (相配) || || ?(有待比較)
匹配串: P(1) p(2) …… p(k-1) p(k)
現(xiàn)在我們把前面總結(jié)的關(guān)系綜合一下
有:
S(1)…s(i-j +1)… s(i-k +1) s(i-k +2) …… s(i-1) s(i) ……
|| (相配) || || || ≠(失配)
P(1) ……p(j-k+1) p(j-k+2) ….... p(j-1) p(j)
|| (相配) || || ?(有待比較)
P(1) p(2) ……. p(k-1) p(k)
由上,我們得到關(guān)系:
‘p(1) p(2) p(3)…..p(k-1)’ = ’ s(j-k+1)s(j-k+2)……s(j-1)’
接下來看“反之,若模式串中存在滿足式(4-4)。。。。。。?!边@一段。看完這一段,如果下面的看不懂就不要看了。直接去看那個next函數(shù)的源程序。(偽代碼)
K 是和next有關(guān)系的,不過在最初看的時候,你不要太追究k到底是多少,至于next值是怎么求出來的,我教你怎么學會。
課本83頁不是有個例子嗎?就是 圖4.6
你照著源程序,看著那個例子慢慢的推出它來??纯茨阕龅氖遣皇呛驼n本上正確的next值一樣。
然后找?guī)椎谰毩曨}好好練練,一定要做熟練了?,F(xiàn)在你的腦子里已經(jīng)有那個next算法的初步思想了,再回去看它是怎么推出來的,如果還看不懂,就繼續(xù)做練習,做完練習再看。相信自己?。?!
附:
KMP算法查找串S中含串P的個數(shù)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!=T[j+1] j=0 )
j=next[j] ; //遞推計算
if(T==T[j+1])next=j+1;
else next=0; //
}
}
inline string::size_type COUNT_KMP(const string S,
const string T)
{
//利用模式串T的next函數(shù)求T在主串S中的個數(shù)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;
}
補上個Pascal的KMP算法源碼
PROGRAM Impl_KMP;
USES
CRT;
CONST
MAX_STRLEN = 255;
VAR
next : array [ 1 .. MAX_STRLEN ] of integer;
str_s, str_t : string;
int_i : integer;
Procedure get_nexst( t : string );
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
j := j + 1; k := k + 1;
next[j] := k;
end
else k := next[k];
end;
End;
Function index( s : string; t : string ) : integer;
Var
i, j : integer;
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 = t[j] ) then
begin
i := i + 1; j := j + 1;
end
else j := next[j];
if j Length(t) then index := i - Length(t);
end;
End;
BEGIN
ClrScr;
Write(s = );
Readln(str_s);
Write(t = );
Readln(str_t);
int_i := index( str_s, str_t );
if int_i 0 then
begin
Writeln( Found , str_t, in , str_s, at , int_i, . );
end
else
Writeln( Cannot find , str_t, in , str_s, . );
END.
index函數(shù)用于模式匹配,t是模式串,s是原串。返回模式串的位置,找不到則返回0
不再贅述算法原理,下面是兩個函數(shù),已經(jīng)通過測試,可以直接用。
private int[] get_nextval(String t) {
int len = t.length();
int i = 0;
int j = -1;
int next[] = new int[len];
while (i len - 1) {
if (j == -1 || (t.charAt(i) == (t.charAt(j)))) {
i++;
j++;
if (t.charAt(i) != (t.charAt(j))) {
next[i] = (j + 1);
} else {
next[i] = next[j];
}
} else {
j = (next[j] - 1);
}
}
return next;
}
private int index_KMP(String s, String t, int[] next) {
int i = 0;
int j = 0;
while (i s.length() - 1 j t.length() - 1) {
if (j == 0 || (s.charAt(i) == t.charAt(j))) {
i++;
j++;
} else
j = (next[j] - 1);
}
if (j t.length() - 2) {
return (i - t.length() + 1);
} else
return -1;
}
使用Boyer-Moore算法
或者使用KMP算法
建議使用后者
KMP算法(java)
public class KMP {
/**
* @param args
*/
//計算模式串的next值
public static void getNext(String strModel, int dNext[]){
int i = 0,j = 1;
dNext[1] = 0;
while(j strModel.length()){
while(i 0 strModel.charAt(i) != strModel.charAt(j))//遞推
i = dNext[i];
i++;
j++;
if(j == strModel.length())
break;
if(strModel.charAt(j) == strModel.charAt(i))//得出next值
dNext[j] = dNext[i] + 1;
else
dNext[j] = i;
}
}
//利用next值查詢子串
public static int getSubString(String strMain, String strModel, int dStart){
int dPos = -1;
int i = dStart;
int j = 1;
int dNext[] = new int[200];
getNext(strModel, dNext);
while(istrMain.length()){
if(strMain.charAt(i) == strModel.charAt(j)){//當前字符匹配
if(j == (strModel.length()-1)){//查找成功
dPos = i - j + 1;
break;
}
i++;
j++;
}
else{//當前字符不匹配
if(dNext[j] == 0){
i++;
j = 1;
}
else{
j = dNext[j];
}
}
}
return dPos;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
String strModel = " jlsdjflskjdm";
int[] dNext = new int[20];
getNext(strModel, dNext);
for(int i = 1; istrModel.length(); i++)
System.out.print(dNext[i] + " ");
String strMain = " aaaaaaaaaaabbbcdabbksfjlsdjflskjd";
System.out.println();
System.out.println(getSubString(strMain, strModel, 1));
}
}
KMP模式匹配算法
KMP算法是一種改進的字符串匹配算法,其關(guān)鍵是利用匹配失敗后的信息,盡量減少模式串與主串的匹配次數(shù)以達到快速匹配的目的明[4]。
求得模式的特征向量之后,基于特征分析的快速模式匹配算法(KMP模式匹配算法)與樸素匹配算法類似,只是在每次匹配過程中發(fā)生某次失配時,不再單純地把模式后移一位,而是根據(jù)當前字符的特征數(shù)來決定模式右移的位數(shù)[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內(nèi)部字符的游標
int i;//指向T內(nèi)部字符的游標
int j=0;//指向P內(nèi)部字符的游標
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算法也是比較著名的模式匹配算法。是由 D.E.Knuth,J.H.Morrs 和 VR.Pratt 發(fā)表的一個模式匹配算法??梢源蟠蟊苊庵貜捅闅v的情況。
如果使用暴風算法的話,前面五個字母完全相等,直到第六個字母 "f" 和 "x" 不相等。如下圖:
T = “abcdex”
j 123456
模式串 abcdex
next[j] 011111
T = "abcabx"
j 123456
模式串T abcabx
next[j] 011123
T = "ababaaaba"
j———————123456789
模式串T——— ababaaaba
next[j]————011234223
T = "aaaaaaaab"
j———————123456789
模式串T——— aaaaaaaab
next[j]————012345678
next數(shù)組其實就是求解字符串要回溯的位置
假設(shè),主串S= “abcababca”;模式串T=“abcdex”,由以上分析得出next數(shù)組為011111,next數(shù)組意味著當主串與模式串不匹配時,都需要從第一個的位置重新比較。
KMP算法也是有缺陷的,比如主串S=“aaaabcde”,模式串T= “aaaaax”。next的數(shù)組就是012345;
當開始匹配時,當i= 5,j = 5時,我們發(fā)現(xiàn)字符"b"與字符“a”不相等,如上圖,j = next[5] = 4;
由于T串的第二、三、四、五位置的字符都與首位“a”相等,那么可以用首位next[1]的值去取代與它相等的后續(xù)字符的next[j],那么next數(shù)組為{0,0,0,0,0,5};
在求解nextVal數(shù)組的5種情況
當前文章:kmpjava算法代碼 kmp算法應用實例
當前網(wǎng)址:http://aaarwkj.com/article42/docpjhc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、網(wǎng)站收錄、外貿(mào)網(wǎng)站建設(shè)、建站公司、虛擬主機、網(wǎng)站策劃
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)