字串的模式匹配問題:
一共有兩種演算法,
1.樸素模式匹配演算法。
舉例而言(尋找從s=」goodgoogle」中找到v=」google」這個子串):我們一般需要以下的步驟
(1).從主串的第乙個字元開始,s與
v中的字元逐一比較,可以發現前三個匹配成功而第四個沒有匹配成功(豎線代表成功,折現代表失敗)。
(2)主串的開始下表+1
,又繼續與子串進行匹配
(3)如果沒有匹配成功那麼繼續重複第二步,直到全部匹配成功,或者直到s到達末尾匹配失敗。
實現**:
對於上面的演算法,我提出一些改進意見就是,匹配的終止條件可以具體一些,減少迴圈的次數。當主串的剩餘子串長度小於要尋找的子串長度時,就可以停止匹配了。//返回子串t在主串s中第pos個字元之後的位置。若不存在,則函式返回值為0.
//t非空,1<= pos <=s.length
public int ndex(string s,string v,int pos)else
}
可以在while中比較兩個字串相等位置的**之前,加乙個大的判斷
if(s.length-1 - i
,如果滿足條件直接
break
,跳出迴圈,後面的字元可以不用比較。
2.kmp模式匹配演算法(是對
1演算法的改進)。
假如有主串 s= 「abcdefgab」; 匹配子串
:t=」abcdex」;我們使用上面的樸素匹配法過程如下。
如果我們認真觀察其實可以發現②③④⑤步驟是不需要的,是重複的無用操作。因為我們可以發現對於子串的首字元a
並不與後面任意乙個字元相等,並且如果出現①中的這種現象,子串的前
5個字元與主串相等,那麼就意味著子串
t不可能在於主串s中的
2-5號字元相等,
2-5號操作是多餘的。這就是
kmp演算法改進樸素演算法的地方。
kmp模式匹配演算法的核心是:如果我們知道子串
t的首字元與
t中後面的字元均不相等(這是前提),如果在出現如①的情況,即子串的前部分與主串的前部分字元相等,但是從
i號不相等,那麼我們可以斷定以
2 到
i-1號任意乙個字元開頭的字串不可能與子串匹配成功,那麼主串的
2 到
i-1號不需要進行判斷,直接從
i號開始判斷。
如果子串中有與首字元重複的子符,該怎麼辦?我們以s=」abcabcabc」 t=」abcabx」為例說明。首先繼續樸素匹配演算法。
因為首字元a有重複,我們不能繼續運用上面的規則,但是我們可以發現,到第二個出現首字元之前的字元我們是可以使用規則,將其規避掉,即②與③去掉,不要判斷。
因此:對於子串中有與首字元相等的字元,可以省略掉一部分不需要的判斷。
這裡如何判斷與首字元相同的不同位置字元,對演算法的影響,參考《大話資料結構》p139.
資料結構 字串 模式匹配
我們先把模式串標出序號 接著把模式串所有字首依次列出來 接下來把每乙個子串相等的字首和字尾的最大長度求出,舉個例子 abaab 觀察子串,前字尾ab相同,因此返回2 5.依次類推,我們可以得到每乙個子串對應的一組序列 當時這組資料並不是所要求的next陣列,可以將其稱為部分匹配值表,相應c 如下 獲...
資料結構 字串的模式匹配
什麼叫做模式匹配呢?其實就是看字串s中是否有子串t,那麼t就叫匹配串。我們平時查詢方式是逐個匹配,那麼時間複雜度就是o n m 比如s abcabde t abd 那麼比較的時候s 1 t 1 所以接下來比較s 2 和t 2 結果s 2 t 2 那麼接下來就比較s 3 和t 3 這一次比較匹配不上。...
資料結構 字串匹配
演算法 如下,包括暴力匹配和kmp演算法。參考 include stringmatching.h stringmatching stringmatching void stringmatching stringmatching void 返回子串t在主串s中第pos個字串之後的位置。若不存在,則返回...