問題描述:若是子串T在主串中存在,則返回存在的位置,若是不存在,則返回-1。算法
1.基本方法spa
從主串的第pos位置字符開始和模式子串字符比較,若是相等,則繼續逐個比較後續字符;不然從主串的下一個字符起再從新和模式子串的字符比較。直到找到匹配字符串或者是主串結尾。指針
僞代碼以下:code
Index(T,S,pos) i <- pos j <- 1 while i<=length[T] and j<=length[S] if T[i]=S[j] i++ j++ else i <- i-j+2 j <- 1 if j> length[S] return i-lenght[S] else return -1;
例如,主串T爲:ababcabababab,子串爲ababa,上述過程以下圖所示。blog
源代碼以下:ip
/* 檢測從主串T的pos位置開始,是否有和子串S匹配,若是有返回匹配開始位置,若是沒有,返回-1 T:主串 S:子串 tlength:主串長度 slength:子串長度 pos:主串開始位置 */ int Index (char T[],char S[],int tlength,int slength,int pos) { int j=0,i=pos; while(i<tlength&&j<slength) { if(T[i]==S[j]) { i++; j++; } else { i=i-j+1; j=0; } } return j==slength?i-slength:-1; }
運行結果以下:字符串
完成源代碼見文章最後!get
2.KMP算法class
由上述基本方法匹配過程當中,不少次的比較都沒有意義的,好比當第一個主串的c與子串中的a不匹配時,下一次的 主串的b和子串的a(第一個)的比較能夠經過分析子串的特色直接跳過此次比較。KMP算法就是爲了告訴咱們,咱們應該每當一趟匹配過程當中出現比較不等時,咱們不須要回溯i指針。而是利用已經獲得的「部分匹配」的結果將模式子串想右「滑動」儘量遠的距離,而後繼續比較。那麼咱們應該如何肯定這個儘量遠的距離哪?file
咱們經過分析子串P1P2..Pm的特色,能夠得出這個「儘量遠的距離的計算方法」。
咱們假設主串S1S2...Sn和子串P1P2...Pm在主串i和主串j位置不匹配,咱們假設咱們但願下次子串k(k<j)位置與主串i位置進行比較,即
P1P2...Pk-1=Si-k+1...Si-1
因爲在匹配過程當中主串中的第i和子串中的第j和不相等,也就是說子串位置j前面的全部都匹配了,即:
Pj-K+1...Pj-1=Si-k+1...Si-1
由上面兩個等式的:
P1P2...Pk-1=Pj-K+1...Pj-1
也就是說,要想在當不匹配時,子串向右滑動最遠距離,只要找到子串中知足上式的最大k值便可,
咱們用next[j]表示當模式子串中第j個字符與主串中相應的字符「失配」時,在模式中須要從新和主串中該字符比較的字符的位置。
在求得next後,匹配過程進行以下:
假設以指針i和j分別指示主串和模式子串中正待比較的字符,令i的初值爲pos,j的初值爲0.若在匹配過程當中Si=Pj,則i和j分別加1,不然,i不變,而j退到next[j]的位置再比較,若相等,則指針各增1,不然,j再退到下一個next值的位置,依次類推,直到下面兩種可能:一種是j退到某個next值的字符比較相等,則指針各自增1,繼續進行匹配;另外一種是j退到0(即模式的第一個字符失配),則此時須要將模式繼續向右滑動一個位置,即從主串的下一個字符Si+1起和模式從新開始匹配。
舉例說明:
例如,主串T爲:acabaabaabcacaabc,子串爲abaabcac,上述過程以下圖所示。
首先計算出zi串next[]={0,1,1,2,2,3,1,2},匹配過程以下:
實現程序以下:
int KMP_Index(char T[],char S[],int tlength,int slength,int pos) { int *next=(int*)malloc(slength*sizeof(int)); KMP_Next(S,next,slength); int j=-1,i=pos-1; while(i<tlength&&j<slength) { if(j==-1||T[i]==S[j]) { i++; j++; } else j=next[j]; } return j==slength?i-slength:-1; }
程序源代碼實現:StringPatternMatching.zip