kmp算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是根据给定的模式串W1,m,定义一个next函数。next函数包含了模式串本身局部匹配的信息。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
intKMP(stringW,stringT){inti=1,j=1;while(i<=n){while(j!=0&&W[j]!=T[i]){j=next[j];}if(j==m){returni-m+1;//success,returnthefirstmatchposition}else{j++;i++;}}return-1;//failure} |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
procedureKMPbegini=1j=1whilei<=ndowhilej<>0andW[j]<>T[i]doj=newnext[j]endwhileifj=mreturn“success”elsej++i++endifendwhilereturn“failure”end |
|
1
2
3
4
5
6
7
8
9
10
11
12
|
voidgetNext(stringW){for(inti=1;i<m;i++){intj=i;while(j>0){j=next[j];if(W[j]==W[i]){next[i+1]=j+1;break;}}}} |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
functionNEXTbeginnext[1]=newnext[1]=0j=2whilej<=mdoi=next[j-1]whilei<>0andW[i]<>W[j-1])doi=next[i]endwhilenext[j]=i+1j=j+1endwhileendfunctionNEWNEXTbeginnewnext⑴=0j=2whilej<=mdoi=next(j)ifi=0orW[j]<>W[i+1]newnext[j]=ielsenewnext[j]=newnext[i]endifj++endwhileend |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
voidGetNext(charT[],intnext[]){next[1]=0;j=1;k=0;while(j<T[0])if((k==0)||(T[j]==T[k])){j++;k++;next[j]=k;}elsek=next[k];} |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
procedureBMbegini=mRepeatj=mk=iwhile(j>0)and(w[j]=t[k])doj=j-1k=k-1endwhilei=i+d[t[i]]Until(j=0)or(i>n)Ifj=0return“SUCCESS”elsereturn“FAILURE”endifend |
|
1
2
3
4
5
6
7
8
9
|
functiond:integer;beginforx∈∑dod(x)=mforj=m-1downto1doifd(w[j])=md(w[j]):=m-jendforendxi+1=ord(ti+1)dm-1+ord(ti+2)dm-2+…+ord(ti+m)=(xi-ord(ti)dm-1).d+ord(ti+m) |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
programRK;begin{计算x,x:=d↑(m-1)modq}x=1fori=1tom-1dox=(32*x)modq{计算模式W的散列函数值}s=0fori=1tomdos=((s*32)+ord(w[i]))modq{计算正文T的第一个长度为m的字符段的散列函数值}t=0fori=1tomdot=(t*32+ord(w[i]))modq{如果正文的第一个长度为m的字符段和模式有相同的散列函数值,则进行匹配检查.否则,以及在匹配检查失败情况下,继续计算下一个字符段的散列函数值}i=1whilei<=n-mdoifs=t{进行匹配检查}k=1j=iwhile(t[j]=w[k])and(k<=m)doj=j+1k=k+1endwhileifi<n-m{计算下一字符段的散列函数值}t=((t-x*ord(t[i]))*32+ord(t[i+m]))modqi=i+1endifendifendwhilereturn“FAILURE”end |
|
下标i
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
|
p(i)
|
a
|
b
|
c
|
d
|
a
|
a
|
b
|
c
|
a
|
b
|
|
next[i]
|
-1
|
0
|
0
|
0
|
0
|
1
|
1
|
2
|
3
|
1
|
|
下标i
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
|
p(i)
|
a
|
b
|
c
|
d
|
a
|
a
|
b
|
c
|
a
|
b
|
|
next[i]
|
-1
|
0
|
0
|
0
|
0
|
1
|
1
|
2
|
3
|
1
|
|
优化的next[i]
|
-1
|
0
|
0
|
0
|
-1
|
1
|
0
|
0
|
3
|
0
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
voidgetNext(constchar*pattern,intnext[]){next[0]=-1;intk=-1,j=0;while(pattern[j]!=‘\0‘){while(k!=-1&&pattern[k]!=pattern[j])k=next[k];++j;++k;if(pattern[k]==pattern[j])next[j]=next[k];elsenext[j]=k;}} |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#include<iostream>#include<stdlib.h>#include<vector>usingnamespacestd;inlinevoidNEXT(conststring&T,vector<int>&next){//按模式串生成vector,next(T.size())next[0]=-1;for(inti=1;i<T.size();i++){intj=next[i-1];while(T[i]!=T[j+1]&&j>=0)j=next[j];//递推计算if(T[i]==T[j+1])next[i]=j+1;elsenext[i]=0;//}}inlinestring::size_typeCOUNT_KMP(conststring&S,conststring&T){//利用模式串T的next函数求T在主串S中的个数count的KMP算法//其中T非空,vector<int>next(T.size());NEXT(T,next);string::size_typeindex,count=0;for(index=0;index<S.size();++index){intpos=0;string::size_typeiter=index;while(pos<T.size()&&iter<S.size()){if(S[iter]==T[pos]){++iter;++pos;}else{if(pos==0)++iter;elsepos=next[pos-1]+1;}}//whileendif(pos==T.size()&&(iter-index)==T.size())++count;}//forendreturncount;}intmain(intargc,char*argv[]){stringS="abaabcacabaabcacabaabcacabaabcacabaabcac";stringT="ab";string::size_typecount=COUNT_KMP(S,T);cout<<count<<endl;system("PAUSE");return0;} |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
PROGRAMImpl_KMP;USESCRT;CONSTMAX_STRLEN=255;VARnext:array[1..MAX_STRLEN]ofinteger;str_s,str_t:string;int_i:integer;Procedureget_nexst(t:string);Varj,k:integer;Beginj:=1;k:=0;whilej<Length(t)dobeginif(k=0)or(t[j]=t[k])thenbeginj:=j+1;k:=k+1;next[j]:=k;endelsek:=next[k];end;End;Functionindex(s:string;t:string):integer;Vari,j:integer;Beginget_next(t);index:=0;i:=1;j:=1;while(i<=Length(s))and(j<=Length(t))dobeginif(j=0)or(s[i]=t[j])thenbegini:=i+1;j:=j+1;endelsej:=next[j];ifj>Length(t)thenindex:=i-Length(t);end;End;BEGINClrScr;{清屏,可不要}Write(‘s=’);Readln(str_s);Write(‘t=’);Readln(str_t);int_i:=index(str_s,str_t);ifint_i<>0thenbeginWriteln(‘Found‘,str_t,‘in‘,str_s,‘at‘,int_i,‘.‘);endelseWriteln(‘Cannotfind‘,str_t,‘in‘,str_s,‘.‘);END. |
原文:http://www.cnblogs.com/yongwangzhiqian/p/3957287.html