KMP 其實也不難

2021-10-05 12:40:39 字數 2341 閱讀 2160

引入:尋找子串在源串中的起始位置。

傳統c++**如下:

#include#includeusing namespace std;

//kmp---常規操作

int find_substr_location(string str, string pattern)

else;

} if (flag == true)

else;

} return -1;

}

返回值:-1和其他,對應找不到和找到子串的起始位置下標。n = |s| 為串 s 的長度,m = |p| 為串 p 的長度,考慮最壞的情況即最後乙個字元失配對應的時間複雜度為:o(n) = |p| *( |s| - |p| + 1) 考慮到主串一般遠遠大於子串,所以o(n) = |p|*|s|

字串比較只能依次比較沒有辦法減少,所以考慮減少比較趟數。

核心:跳過不可能匹配成功的字元即依次失配後源串索引的移動不再是加一。

針對模式串引入了next陣列,定義::next[i] 表示 p[0] ~ p[i] 這乙個子串,使得 前k個字元恰等於後k個字元的最大的k,k

改進演算法規則:失配之後源串索引移動很多位,跳過不可能匹配的字元位置,怎麼確定移動多少位?

第一次比較,模式串失配位置為s[3]、p[3]、模式串下標記為p,源串下表記為s,此時失配移動後的模式串下標p = next[p-1]=1、s=3。

第二次比較,起始位置s[3]、p[1],模式串失配位置下標為6,此時失配移動後的模式串下標p = next[p-1]=3,s=8。

第三次比較,起始位置s[8]、p[3]、匹配成功,返回s-p即可。

使用暴力構造next陣列實現的kmp**如下:

//字串擷取方法(start,end)前閉後閉區間

string str_truncation(string str, int start, int end)

else

} }else;

return s;

}// 暴力構建next陣列

void get_next(string pattern, vector&next)

} if (flag==false) }}

int kmp(string str, string pattern)

return 0;

}

問題及解決方案:

下文均以tar、pos來依次代替源串索引、模式串索引。

1.0 考慮到字元比較不相等時會取其失配位置前一位對應的next值為新的pos即 pos= next[pos-1],可能從第乙個元素就失配會造成越界訪問,所以在更新pos位置時判斷是否pos為0,不是則pos= next[pos-1],否則tar+=1.

2.0 字串擷取方法先使用了substr(start,n)方法,浪費大量時間找問題,居然最後是使用的函式有問題,大意了substr(int start,int n) 從start索引位置取n個字元(包括start)。所以後面自己實現了乙個str_truncation來擷取字串。

現在比較的趟數已經大大減少,可否快速構建next陣列?

上圖欲求x位置在next陣列裡的值,將x-1記為now,假設p[x]=d,p[next[now]=p[x]=d,那麼易得出next[x] = next[now]+1。

如果p[x] != d,那麼需要將now的位置左移,移動多少位?按照上圖需要移動至now=next[now-1]即2,再來比較p[x]是否等於p[now],p[now]不等於p[x]時需要縮減now (now = next[now-1])直至p[x]=p[now],此刻如果now不等於0的條件下next[x] = next[now-1]+1。

next快速構建**如下:

// 快速構建next陣列

void get_next_fast(string pattern, vector& next)

{ next.push_back(0);

int x = 1;

int now = 0;

while ( x時間複雜度o(n)=m,再加上kmp匹配的複雜度為o(n) = n,總複雜度:o(n) = n+m 

加薪其實也不難 加薪五步曲

對於剛剛從校園出來的大學生來說,能夠撈到乙份薪水基本滿意的差事,就要謝天謝地了。但有人卻沒有對此露出滿意的微笑。譬如我的朋友小芹菜,儘管她剛從大學畢業,所學專業也不熱門,無任何就業優勢,可她卻不僅不滿足乙份像樣的工作,還不斷尋求加薪的機會。加薪一步曲心裡慌慌慌 第一次提出加薪和所有三流大學出來的畢業...

運維其實不難

運維不難?恐怕有人要扔鞋子了 1 系統不是我們開發的,維護中很多東西搞不定要找開發 實施的 2 找他們,要麼忙,要麼說幾句,搞得似懂非懂.3 開發中的遺留問題導致重大事件,運維成了替罪羊.4 客戶口頭說了兩句,日後有事就怪執行規範 5 客戶要提數 臨時安排任務 開發實施要做緊急配合,忙得不可開交.運...

Spring實現AOP 其實不難

aop實戰之旅 不基於註解 ioc 控制反轉 ioc 通俗點來講,就是把物件的建立交給spring容器來管理,不用我們手動new aop 定義乙個切面,在切面中執行特定 實現 增強,常用於日誌列印,異常處理,效能耗時計算,事務處理,安全驗證等等,每個方法都要寫記錄日誌的 多,工作量大 日誌統一交給某...