时间轴
KMP
题目:
实际上直接用 C++的 string.find 函数就能求值
1234567 | #include <string>using std::string;class Solution {public: int strStr(string haystack, string needle) { return haystack.find(needle); }}; |
但是显然这题考察 KMP :
123456789101112131415161718192021222324252627282930313233343536373839 | 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 数组的例子
我们用最经典的模式串:
下标:
12 | index: 0 1 2 3 4 5 6p : a b a b a c a |
我们要求next[i]:
1 | next[i] = p[0..i] 的最长相同前后缀长度 |
前缀:从开头开始后缀:从结尾结束(但不能等于整个字符串)
初始化
因为:“a” 没有前后缀
i = 1
12 | p[1] = bp[j] = p[0] = a |
比较:b != a,因为j = 0,不能再回退。
当前:
i = 2
12 | p[2] = ap[j] = p[0] = a |
匹配成功:
所以:
当前:
解释:
123456 | aba前缀: a ab后缀: a ba最长相同 = a长度 = 1 |
i = 3
12 | p[3] = bp[j] = p[1] = b |
匹配:
当前:
解释:
12345 | abab前缀: a ab aba后缀: b ab bab最长 = ab |
i = 4
12 | p[4] = ap[j] = p[2] = a |
匹配:
当前:
解释:
i = 5(关键回退)
12 | p[5] = cp[j] = p[3] = b |
不匹配:
开始回退:
123 | j = next[j-1]j = next[2]j = 1 |
继续比较:
仍然不匹配:
123 | j = next[j-1]j = next[0]j = 0 |
现在:j = 0 停止。
当前:
i = 6
12 | p[6] = ap[j] = p[0] = a |
匹配:
最终结果
123 | p = a b a b a c ai = 0 1 2 3 4 5 6next = 0 0 1 2 3 0 1 |