[Leetcode] Implement strStr()
Implement strStr().
Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack.
KMP算法!
1 class Solution { 2 public: 3 void getNext(vector<int> &next, string &needle) { 4 int i = 0, j = -1; 5 next[i] = j; 6 while (i != needle.length()) { 7 while (j != -1 && needle[i] != needle[j]) j = next[j]; 8 next[++i] = ++j; 9 } 10 } 11 int strStr(string haystack, string needle) { 12 if (haystack.empty()) return needle.empty() ? 0 : -1; 13 if (needle.empty()) return 0; 14 vector<int> next(needle.length() + 1); 15 getNext(next, needle); 16 int i = 0, j = 0; 17 while (i != haystack.length()) { 18 while (j != -1 && haystack[i] != needle[j]) j = next[j]; 19 ++i; ++j; 20 if (j == needle.length()) return i - j; 21 } 22 return -1; 23 } 24 };
上面的是通常用的KMP算法,但是算法是有一定缺陷的。比如我们的模式串 pattern =“AAAAB”,其中很容易得到next数组为01230。如果目标匹配串为 “AAAACAAAAB” ,大家可以模拟一下,A要回溯多次。就是说我们的next数组优化并不彻底。优化算法:next[i]表示匹配串在i处如果匹配失败下次移到的位置。下面是优化后的的求next数组的代码。虽然两种写求得next值不一样,但是kmp函数的写法是一样的。
1 class Solution { 2 public: 3 void getNext(vector<int> &next, string &needle) { 4 int i = 0, j = -1; 5 next[i] = j; 6 while (i < needle.length() - 1) { 7 while (j != -1 && needle[i] != needle[j]) j = next[j]; 8 ++i; ++j; 9 //特殊情况,这里即为优化之处。考虑下AAAAB, 防止4个A形成0123在匹配时多次迭代。 10 if (needle[i] == needle[j]) next[i] = next[j]; 11 else next[i] = j; 12 } 13 } 14 int strStr(string haystack, string needle) { 15 if (haystack.empty()) return needle.empty() ? 0 : -1; 16 if (needle.empty()) return 0; 17 vector<int> next(needle.length() + 1); 18 getNext(next, needle); 19 int i = 0, j = 0; 20 while (i != haystack.length()) { 21 while (j != -1 && haystack[i] != needle[j]) j = next[j]; 22 ++i; ++j; 23 if (j == needle.length()) return i - j; 24 } 25 return -1; 26 } 27 };
下面不是KMP算法,但是代码特别简洁:
1 class Solution { 2 public: 3 int strStr(string haystack, string needle) { 4 int i, j; 5 for (i = j = 0; i < haystack.size() && j < needle.size();) { 6 if (haystack[i] == needle[j]) { 7 ++i; ++j; 8 } else { 9 i -= j - 1; j = 0; 10 } 11 } 12 return j != needle.size() ? -1 : i - j; 13 } 14 };