【LeetCode】字符串匹配


給定目標串 haystack 和模式串 needle ,返回 needle 在 haystack 中第一次出現的位置下標,若 needle 不是 haystack 的子串則返回 -1。

1. Brute-Force Algorithm(暴力算法 / 簡單模式匹配)

    我自己寫了一種雙層循環的

 1 int strStr(string haystack, string needle) {
 2     if (needle.empty()) return 0;
 3     int m = haystack.size(), n = needle.size();
 4     for (int i = 0; i <= m - n; i++) {
 5         for (int j = 0; j < n; j++) {
 6             if (needle[j] != haystack[i + j])
 7                 break;
 8             if (j == n - 1)
 9                 return i;
10         }
11     }
12     return -1;
13 }

    看了答案發現了一種更高效的方法,雖然時間復雜度同樣是 O(m*n),但只要一層循環,非常Nice!

 1 int strStr(string haystack, string needle) {
 2     if (needle.empty()) return 0;
 3     int i = 0, j = 0;
 4     int m = haystack.size(), n = needle.size();
 5     while (i < m && j < n) {
 6         if (haystack[i] == needle[j]) {
 7             i++;
 8             j++;
 9         } else {
10             i = i - j + 1;
11             j = 0;
12         }
13         if (j == n)
14             return i - j;
15     }
16     return -1;
17 }

 

2.  KMP算法

算法講解可以參考 http://www.61mon.com/index.php/archives/183/ ,講解的已經很好了。

KMP的時間復雜度僅為 O(m+n),因為當出現子串與主串某處不匹配時,並不會將遍歷主串的下標 i 回溯,而是利用得到的 next 數組將模式子串向右“滑動”盡可能遠的一段距離,繼續進行比較,提高了效率。

next 數組的求解是關鍵,它是基於模式子串的最長前后綴,next[i] = needle[0] 到 needle[i - 1] 的字符串的最長相同前后綴的長度。

 1 void getNext(string needle, vector<int> &next) {
 2     int i = 0, j = -1;
 3     // j 表示最長相同前后綴的長度
 4     next[0] = j;
 5     while (i < needle.size()) {
 6         // j == -1 為邊界條件判斷, j = next[j] 可能使 j 退回到 -1
 7         if (j == -1 || needle[i] == needle[j]) {
 8             i++;
 9             j++;
10             next[i] = j;
11         } else {
12             j = next[j];
13         }
14     }
15 }
16     
17 int strStr(string haystack, string needle) {
18     if (needle.empty()) return 0;
19     int i = 0, j = 0;
20     int m = haystack.size(), n = needle.size();
21     vector<int> next(n + 1);
22     getNext(needle, next);
23     while (i < m && j < n) {
24         if (j == -1 || haystack[i] == needle[j]) {
25             i++;
26             j++;
27         } else {
28             j = next[j];
29         }
30         if (j == n)
31             return i - j;
32     }
33     return -1;
34 }

     改進的KMP算法

 1 void getNextval(string needle, vector<int> &nextval) {
 2     int i = 0, j = -1;
 3     nextval[0] = j;
 4     while (i < needle.size()) {
 5         if (j == -1 || needle[i] == needle[j]) {
 6             i++;
 7             j++;
 8             // 生成 nextval 數組
 9             if (needle[i] != needle[j])
10                 nextval[i] = j;
11             else
12                 nextval[i] = nextval[j];
13         } else {
14             j = nextval[j];
15         }
16     }
17 }
18     
19 int strStr(string haystack, string needle) {
20     if (needle.empty()) return 0;
21     int i = 0, j = 0;
22     int m = haystack.size(), n = needle.size();
23     vector<int> nextval(n + 1);
24     getNextval(needle, nextval);
25     while (i < m && j < n) {
26         if (j == -1 || haystack[i] == needle[j]) {
27             i++;
28             j++;
29         } else {
30             j = nextval[j];
31         }
32         if (j == n)
33             return i - j;
34     }
35     return -1;
36 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM