Leetcode Algorithm #28 Implement strStr()
topic content
Implement strStr().
Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
Example 1:
Input: haystack = "hello", needle = "ll" Output: 2
Example 2:
Input: haystack = "aaaaa", needle = "bba" Output: -1
problem solving
Generally, the first thing that comes to mind when seeing string matching is the most classic KMP algorithm, but it has been a long time since the last time the KMP algorithm was used. It is difficult to deduce it without checking it, so I will review it here. See Knuth–Morris–Pratt (KMP) Pattern Matching (Substring search)
The first is to perform a generation prefix
preprocessing on the search target, such as the search string p
, the character whose index is i
the character, the corresponding prefix
value should be 0~i-1
the longest string of the prefix and suffix at the same time (called such a string as the prefix and suffix) . suffix string ) end position. After reviewing this definition, I have a good understanding of the purpose of looping forward in KMP while
, which is to constantly check whether there is such a prefix and suffix string, which satisfies the character after the prefix is the same as the current character to be matched. If If there is no identical, the flag bit will go back to the front.
Assuming a string, now the strings of 0-5 and 10-15 constitute a prefix and suffix string, now the character X at the test position 16, the 6th character is not equal to X, so we perform forward tracing, find a more Small suffix strings, such as 0-3 and 12-15, are a suffix string. At this time, the 4th character is the same as X, so pos[16] = 4
.
class Solution {
public:
int strStr(string haystack, string needle) {
init(needle);
int cur1 = 0, cur2 = -1, len = haystack.length(), need = needle.length();
if (need == 0)
return 0;
for (; cur1 < len; ++cur1) {
while (cur2 > -1 && needle[cur2+1] != haystack[cur1])
cur2 = pos[cur2];
if (needle[cur2+1] == haystack[cur1])
++cur2;
if (cur2 == need - 1)
return cur1 - need + 1;
}
return -1;
}
private:
int pos[50000];
void init(string needle) {
// cur1为用于设置pos值的前方指针,cur2为用于测试最长前后缀字符串的指针
int len = needle.length(), cur1 = 1, cur2 = -1;
pos[0] = -1;
for (; cur1 < len; ++cur1) {
// 不满足前缀后字符与测试字符相同和未回到原位时,前溯测试更短的前后缀字符串
while (cur2 > -1 && needle[cur2+1] != needle[cur1])
cur2 = pos[cur2];
if (needle[cur2+1] == needle[cur1])
++cur2;
pos[cur1] = cur2;
}
}
};