BF算法 时间复杂度(O(nm))
一个一个遍历 不多赘述
KMP算法 时间复杂度(O(m+n))
kmp算法有两个点需要注意
点1. 计算模式串的前缀
遍历的时候注意当回到第一个点的时候 或者两点相同的时候 该点的后面一个点等于最大前缀和
点2. 遍历主串移位
遍历的时候同样注意如果回溯到第一个点,让该点前缀和为0,主串指针右移
如果没回溯到第一个点,那么就用next指针找到当前最大前缀长度,前面重复的前缀不用算,只用看后面不相同的即可
#include <iostream>
using namespace std;
const int N = 100010;
int Next[N];
string a, b;
void getNext(string a)
{
int j = 0;
int k = -1;
Next[0] = -1;
while (j < a.length() - 1)
{
if (k == -1 || a[j] == a[k]) // 如果没找到使得k为-1了 或者下标j和下标k代指的数组相同,那么就让最长相等前后缀继续加1
{
Next[++j] = ++k;
}
else
{
k = Next[k]; // 如果不相同 则 往前找 找到上次匹配到的,与这次有可能有相同前缀的子串
}
}
}
int KMP()
{
int i = 0, j = 0;
while (i < a.length() && j < b.length())
{
cout << j << " " << b[j] << " " << i << " " << a[i] << endl;
if (j == -1) // 第一位都匹配不到 你就直接往后走吧
{
i++;
j = 0;
}
else if (b[j] == a[i]) // 如果相等 指针全部右移
{
++i;
++j;
}
else // 如果不相等的话,找到该点前面点的前缀和,让指针从前面那个点所在的最大前缀和的点 开始遍历
{
j = Next[j];
}
cout << i << " " << j << " " << endl;
// if (j == b.length() - 1)
// break;
// 注释掉的地方是我画蛇添足了,仔细想一下,在n-1处就能停止了吗?不,应该还要用在n-1处的数值检验一次,对了直到length才能出去
}
cout << i << " " << j << endl;
return i - j + 1;
}
int main()
{
cin >> a >> b;
getNext(b);
KMP();
}