给一个主串s,在给一个子串substr,判断substr是否为s的子串
一、BF 暴力搜索
暴力,依次逐个比较字符,先从主串和模式串的第一个字符开始,如果相等一起比较下一个字符,如果不相等,那么重新回到模式串第一个,主串的第二个来进行比较。
class BF
{
public:
bool My_BF(string s, string substr)
{
int i = 0, j = 0;
while (i < s.size() && j < substr.size())
{
int begin = i + 1; // 标记主串下一个位置
while (i < s.size() && j < substr.size() && s[i] == substr[j])
{
i++; //如果相等就一起往后遍历
j++;
}
if (j == substr.size()) // 当while循环跳出,判断是否到大子串边界
return true; // 如果到了就说明匹配成功了
else
{
i = begin; // 如果没有到说明ij字符不相等
j = 0;
}
}
return false;
}
};
二、KMP算法
显然O(M*N)的时间复杂度让人叹为观止
① 区分前缀后缀与最长相同前后缀
存在相等前后缀:aa
② 写出next数组 即 010120为所求
void GetNext(string s, vector<int>& next)
{
int j = 0;
next[0] = 0;
for (int i = 1; i < s.size(); ++i)
{
while (j > 0 && s[i] != s[j])
j = next[j - 1];
if (s[i] == s[j])
j++;
next[i] = j;
}
}
class KMP
{
public:
void GetNext(string s, vector<int>& next)
{
int j = 0;
next[0] = 0;
for (int i = 1; i < s.size(); ++i)
{
while (j > 0 && s[i] != s[j])
j = next[j - 1];
if (s[i] == s[j])
j++;
next[i] = j;
}
}bool kmp(string s, string substr)
{
vector<int> next(substr.size());
GetNext(substr, next);
int i = 0, j = 0;
while (i < s.size() && j < substr.size())
{
if (s[i] == substr[j])
{
i++;
j++;
}
else
{
j = next[j - 1];
}
}
if (s[i] == substr[j] && j == substr.size())
return true;
else
return false;
}
};