KMP字符串匹配
本蒟蒻經過一下午的掙扎終于能略微窺探到KMP算法的精妙,也是彌補了以前學數據結構的遺憾,這里記錄一下蒟蒻自己理解的KMP算法,博客簡略,主要是大概過一下,讓自己以后能回憶起來,具體參考《大話數據結構》。
KMP的精妙之處就在于它的next數組,next[i]保存的是第\(i\)個數之前的字符串前后綴相似度,也可以理解為上一個可匹配的前綴字符串下一個字符。求next數組的算法核心就在于\(j\)的回溯,他可以回溯到之前的最長可匹配前綴字串,因為這樣后綴字串就為對應的最長可匹配后綴字串,至于為什么手動模擬一遍\("ababcabababc"\)就知道了(滑稽)。
上代碼:
/*求子串T的next數組*/ void get_next(string T, int *next) {int i = 1, j = 0;next[1] = 0;//守字母next賦值0while (i < T[0])//T[0]儲存子串T長度{if (j == 0 || T[i] == T[j]){i++;j++;next[i] = j;}elsej = next[j];//字符不相同,回溯} }求出了next數組,接下來的KMP就比較好理解了,只回溯\(j\),不回溯\(i\)
int index_KMP(string S, string T, int pos)//返回匹配到的下標 {int i = pos;//pos為S主串開始匹配的位置int j = 1;int next[255];get_next(T, next);while (i <= S[0] && j <= T[0])//i,j小于兩個字符串的大小{if (j == 0 || S[i] == T[j])//和傳統匹配算法相比增加特判{i++;j++;}elsej = next[j];}if (j > T[0])return i - T[0];//返回S中匹配字符串的開頭位置elsereturn 0;//匹配失敗 }但是next數組還是有缺陷,比如主串為\("aaabcde"\),子串為\("aaaaax"\),當\(i=5,j=5\)的時候\(a,b\)不相等,那么\(j\)會從5,4,3一步一步回溯到1,造成時間的浪費,所以下面的nextval是一種提前判斷回溯點,如果回溯點和原來的一樣要回溯就直接回溯到最終位置了。
/*求子串T的nextval數組*/ void get_nextval(string T, int *nextval) {int i = 1, j = 0;nextval[1] = 0;//守字母next賦值0while (i < T[0])//T[0]儲存子串T長度{if (j == 0 || T[i] == T[j]){i++;j++;if (T[j] != T[j])//當前字符的前綴字符不同nextval[i] = j;//正常賦值else//當前字符前綴字符相同,將前綴字符的nextval值賦給在i上的值nextval[i] = nextval[j];}elsej = nextval[j];//字符不相同,回溯} }轉載于:https://www.cnblogs.com/JMWan233/p/11161795.html
總結
- 上一篇: SQL Server 2005 的版本和
- 下一篇: SpringBoot学习之@Config