时间轴
KMP
题目:
实际上直接用 C++的 string.find 函数就能求值
1 2 3 4 5 6 7
| #include <string> using std::string;
class Solution { public: int strStr(string haystack, string needle) { return haystack.find(needle); } };
|
但是显然这题考察 KMP :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| class Solution { public: int strStr(string s, string p) { int n = s.size(), m = p.size(); int i, j;
if(m == 0) return 0;
vector<int> next(m, 0);
j = 0; for(i = 1; i < m; i++){ while(j > 0 && p[i] != p[j]) j = next[j - 1];
if(p[i] == p[j]) j++;
next[i] = j; }
j = 0; for(i = 0; i < n; i++){ while(j > 0 && s[i] != p[j]) j = next[j - 1];
if(s[i] == p[j]) j++;
if(j == m) return i - m + 1; }
return -1; } };
|
求解 next 数组的例子
我们用最经典的模式串:
下标:
1 2
| index: 0 1 2 3 4 5 6 p : a b a b a c a
|
我们要求next[i]:
1
| next[i] = p[0..i] 的最长相同前后缀长度
|
前缀:从开头开始后缀:从结尾结束(但不能等于整个字符串)
初始化
因为:“a” 没有前后缀
i = 1
1 2
| p[1] = b p[j] = p[0] = a
|
比较:b != a,因为j = 0,不能再回退。
当前:
i = 2
1 2
| p[2] = a p[j] = p[0] = a
|
匹配成功:
所以:
当前:
解释:
1 2 3 4 5 6
| aba 前缀: a ab 后缀: a ba
最长相同 = a 长度 = 1
|
i = 3
1 2
| p[3] = b p[j] = p[1] = b
|
匹配:
当前:
解释:
1 2 3 4 5
| abab 前缀: a ab aba 后缀: b ab bab
最长 = ab
|
i = 4
1 2
| p[4] = a p[j] = p[2] = a
|
匹配:
当前:
解释:
i = 5(关键回退)
1 2
| p[5] = c p[j] = p[3] = b
|
不匹配:
开始回退:
1 2 3
| j = next[j-1] j = next[2] j = 1
|
继续比较:
仍然不匹配:
1 2 3
| j = next[j-1] j = next[0] j = 0
|
现在:j = 0 停止。
当前:
i = 6
1 2
| p[6] = a p[j] = p[0] = a
|
匹配:
最终结果
1 2 3
| p = a b a b a c a i = 0 1 2 3 4 5 6 next = 0 0 1 2 3 0 1
|