給定倆個字串str和match,長度分別為n和m。實現乙個演算法,如果字串str中含有字串match,則返回match在str中的開始位置,不含有則返回-1;
str="acbc",match="bc",返回2.
str="acbc",match="bcc",返回-1.
我們知道在match中a區域與b區域是匹配的,所以下次匹配只需要將match[k]和str[j]進行比較即可。之後一直進行這樣的滑動匹配過程,直到在str的某乙個位置把match完全匹配完,就說明str中有match。如果滑動到最後也沒有匹配出來,就說明str中沒有match。
驗證匹配演算法的正確性:
1,上述中,為什麼要直接讓match[k]和str[j]直接比較????
如上圖,假設匹配到a字元和b字元才發生了不匹配,所以c區域必然等於b區域,又因為我們知道nextarr的定義,所以我們也知道b區域也等於a區域,那麼我們就可以直接將match右滑動到如圖所示的位置,直接讓c字元和a字元比較。
2,為什麼a區域和b區域之間肯定匹配不了match呢???
我們用假設法:假設bb區域開始位置是不用檢查的其中乙個位置,如果從這個位置可以匹配出match部分子串,那麼,從match[0]開始也必然存在和bb區域相等的區域aa可以匹配出match部分子串。同時我們注意到aa比a區域大,bb比b區域大,我們找到了比b和a更大的字首和字尾子串。這個結論和求nextarr的值是相互矛盾的。
匹配過程分析完畢:match一直向右滑動,最壞的時間複雜度為o(n).
**:
int getindexof(const char *strcontent, const char *match)
int si = 0;
int mi = 0;
int tmp = new int[strlen(match)];
getnextarray(match,tmp);
while (si < strlen(strcontent) && mi < strlen(match))
else if (next[mi] == -1)
else
}free(next);
if(next != null)
next = null;
return mi == strlen(match) ? si - mi : -1;
}
最後一步求得nextarr陣列:1,對於match[0]而言,它前面沒有字元,所以nextarr[0]規定為-1.對於match[1]來說,在它之前只有match[0],但是nextarr的定義是要求任何子串的字尾不包括第乙個match[0],故nextarr[1]==0.
2,之後的nextarr陣列的值求解過程如下:
int pos = 2;//從下標2開始
int cn = 0;//
while (pos < length)
else if (cn > 0)
else}}
整個kmp演算法的複雜度為o(m)(求解nextarr陣列的過程)+o(n)(匹配的過程),因為有n>=m所以時間複雜度為o(n).
字串匹配問題 KMP匹配演算法
基本思想 字串匹配問題 在文字串中尋找是否有與模式串相同的子串 在字串匹配時,暴力匹配忽略了如果模式串開頭與中間有重複部分,在將模式串的後面的重複部分匹配後,無法繼續匹配的話,此時將模式串開頭實際上也已經被匹配了,可以直接從開頭重複部分之後開始匹配 這裡引入了乙個部分匹配值表,每個與模式串的字元對應...
字串匹配問題 KMP演算法
kmp演算法 kmp是解字串匹配這類題目的演算法,又稱 看毛片 演算法。如下圖,給定乙個長度為n的文字,給定乙個長度為m 的字串,求該字串在給定文字的中出現的次數。kmp就是解決這一類題目的。i 1 zzkzzzkzzzkzkkkz zzkzzkzzkzzk j 1繼續考慮上面的問題。首先我相信每個...
字串匹配問題 KMP演算法
字串匹配問題 給定兩個字串s 主串 和t 模式串 假設n strlen s strlen t m,判斷主串s中是否包含模式t,且返回t在s中所在的起始位置。這裡為簡單起見,若s包含t,則只返回第乙個t所在的位置。一般的蠻力法如下 蠻力法在遇到不匹配時,j每次都要回到t的起點,從新開始匹配,這樣來看效...