面試演算法 字串(二)

2021-08-22 19:31:04 字數 2209 閱讀 1707

kmp演算法可以用來解決字串匹配問題。現在有兩個字串,str1長度為n和str2長度為m且n>=m,判斷是否存在str1中包含str2(也就是判斷str2是否是str1的子串),如果存在,則返回true,如果不存在則返回false。

我們一般的思路是,從str1的第乙個字元開始,擷取和str2相同長度的子串,將兩者人進行比較,直到末尾(真實情況下移動到n-m處結束)這種方式的時間複雜度為o(n*m)。

但是kmp演算法可以將時間複雜度降到o(n+m)。

(引用:

我認為,kmp演算法的優勢在於,減少了比較的次數,如果用傳統思路,我們需要對str1的字元乙個乙個的比較。

舉例來說,有乙個字串"bbc abcdab abcdabcdabde",我想知道,裡面是否包含另乙個字串"abcdabd"?

1、首先,字串"bbc abcdab abcdabcdabde"的第乙個字元與搜尋詞"abcdabd"的第乙個字元,進行比較。因為b與a不匹配,所以搜尋詞後移一位。

2、因為b與a不匹配,搜尋詞再往後移。

3、就這樣,直到字串有乙個字元,與搜尋詞的第乙個字元相同為止。

4、繼續比較str1和str2直到字串有乙個字元,與搜尋詞對應的字元不相同為止。

這裡我們就要引入兩個概念

- "a"的字首和字尾都為空集,共有元素的長度為0;

- "ab"的字首為[a],字尾為[b],共有元素的長度為0;

- "abc"的字首為[a, ab],字尾為[bc, c],共有元素的長度0;

- "abcd"的字首為[a, ab, abc],字尾為[bcd, cd, d],共有元素的長度為0;

- "abcda"的字首為[a, ab, abc, abcd],字尾為[bcda, cda, da, a],共有元素為"a",長度為1;

- "abcdab"的字首為[a, ab, abc, abcd, abcda],字尾為[bcdab, cdab, dab, ab, b],共有元素為"ab",長度為2;

- "abcdabd"的字首為[a, ab, abc, abcd, abcda, abcdab],字尾為[bcdabd, cdabd, dabd, abd, bd, d],共有元素的長度為0。

知道這些概念以後,我們就需要對str2進行預處理,得到乙個next陣列,這個next陣列表示的其實就是str2字串的字首和字尾存在的共有元素的所有情況。

這張圖的t表示str2字串,藍色的段落表示部分匹配值,我們可以看到,但我們從第乙個位置比較str2和str1失敗後,我們可以直接將第一段的藍色線段的最左邊移到右邊藍色線段的最左邊,這樣就避免了中間的重複比較操作,提高了效率。

那麼,這個next陣列應該怎麼求呢?

接下來,我們就要進行str1和str2的字串匹配了,前面得到next陣列中已經儲存了str2字串的子串情況,一旦在比較的過程中出現不匹配的情況,就可以返回到上一次匹配的子串。最後的ans表示的是子串在str1中的開頭元素的座標。

void kmp()

}

這裡可能不好理解,下面的**可以提供一些幫助

面試 演算法(五) 替換字串中的空格

char str 100 hello world 我寫上述 的含義是,我們是在已分配足夠空間的字串的基礎上開始空格的替換的,也即不存在索引越界 再分配記憶體的問題。替換的順序有二 顯然出於效率的考慮,從右向左替換是更為合理的。void replaceblank char str,int len le...

直通BAT面試演算法精講 字串(1)

字串面試題的特點 1.廣泛性 1 字串可以看做字元型別的陣列,與陣列排序 查詢 調整有關 2 很多其他型別的面試題可以看做字串型別的面試題 2.需要掌握的概念 1 回文 2 子串 連續 3 子串行 不連續 4 字首樹 trie樹 5 字尾樹和字尾陣列 6 匹配 7 字典序 3.需掌握的操作 1 與陣...

直通BAT面試演算法精講 字串(3)

空格替換練習題 題幹 給定乙個字串str,將其中所有的空格字元替換成 20 假設str後面有足夠的空間 一般思路 1 遍歷發現空格數量,計算替換後的總長度 2 從右往左依次拷貝字元,遇到空格換為 20 即可。python 可以使用 replace 函式 class solution def repl...