4.2 串的模式匹配
4.2.1 简单的模式匹配算法
Leetcode28 找出字符串中第一个匹配项的下标
给你两个字符串 haystack 和 needle,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1。
主串和模式串都前移。
时间复杂度 O(nm)
class Solution
{
public:
int strStr(string haystack, string needle)
{
int m = haystack.size(), n = needle.size();
for (int i = 0; i + n <= m; i++)
{
int flag = true;
for (int j = 0; j < n; j++)
{
if (needle[j] != haystack[j + i])
{
flag = false;
break;
}
}
if (flag)
{
return i;
}
}
return -1;
}
};
4.2.2 串的模式匹配算法——KMP 算法
前缀:除第一个字符外,字符串的所有头部子串
后缀:除最后一个字符外,字符串的所有尾部子串
部分匹配值:前缀和后缀最长相等前后缀长度
主串不动,模式串前移
时间复杂度 O(m+n)
class Solution {
public:
int strStr(string haystack, string needle) {
int n = haystack.size(), m = needle.size();
if (m == 0) {
return 0;
}
vector<int> pi(m);
for (int i = 1, j = 0; i < m; i++) {
while (j > 0 && needle[i] != needle[j]) {
j = pi[j - 1];//字符不匹配,模式串指针前移
}
if (needle[i] == needle[j]) {
j++;//字符匹配,双指针后移
}
pi[i] = j;//字符匹配,pi[j+1]=pi[j]+1
}
for (int i = 0, j = 0; i < n; i++) {
while (j > 0 && haystack[i] != needle[j]) {
j = pi[j - 1];
}
if (haystack[i] == needle[j]) {
j++;
}
if (j == m) {
return i - m + 1;
}
}
return -1;
}
};
求 next 数组
前后缀相等,next=0 时,i++,j++。否则 j++
next 数组为递增序列
求 nextval 数组
相同直接跳过,重复的字符比较失败不需要多次比较
nextval 数组可能为无序序列