因为看了《大话数据结构》里的KMP算法的实现,里面用的是c语言的写法,因此通过学习整理思路通过C++实现
如果你看不懂为什么要这样做,建议先看看《大话数据结构》或者其他数据结构的书或资料。
首先是:get_next函数
vector<int> get_next(string b) //用vector来保存子串b的next数组
{
vector<int> result; //别想着用()帮它确定大小,其实是添加元素并且默认赋值为0了,建立一个空的容器就OK了
int i, j;
i = 0;
j = -1;
result.push_back(-1); //将容器首元素赋值,作为标识使用
while (i < b.size() - 1)
{
if (j == -1 || b[i] == b[j]) //b[i]表示后缀的单个字符
//b[j]表示前缀的单个字符
{
++i;
++j;
//这里的其实是优化重复的字符
//可以直接用result.push_back(j);代替下面的判断语句
if (b[i] != b[j])
result.push_back(j);
else if (i == 1)
result.push_back(j);
else
result.push_back(result[j]);
}
else
j = result[j]; //若字符不同,前缀字符回溯
}
return result;
}
然后是:KMP函数
int KMP(string a, string b)
{
vector<int> next = get_next(b); //调用get_text函数
int i = 0;
int j = 0;
//注意size函数返回的类型是string::size_type是无符号数
//若i<主串的长度且j<子串的长度时,循环继续
while (i < (int)a.size() && j <(int)b.size())
{
if (j == -1 || a[i] == b[j]) //两字母相等则继续,相对于朴素算法增加了
{
++i;
++j;
}
else {
j = next[j]; //若不相等,j退回合适的位置
}
}
if (j == b.size()) {
return i - j; //这里返回的是匹配字符开始的下标位
}
else {
return -1;
}
}
整体代码:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> get_next(string b)
{
vector<int> result;
int i, j;
i = 0;
j = -1;
result.push_back(-1);
while (i < b.size() - 1)
{
if (j == -1 || b[i] == b[j])
{
++i;
++j;
if (b[i] != b[j])
result.push_back(j);
else if (i == 1)
result.push_back(j);
else
result.push_back(result[j]);
}
else
j = result[j];
}
return result;
}
int KMP(string a, string b)
{
vector<int> next = get_next(b);
int i = 0;
int j = 0;
while (i < (int)a.size() && j <(int)b.size())
{
if (j == -1 || a[i] == b[j])
{
++i;
++j;
}
else {
j = next[j];
}
}
if (j == b.size()) {
return i - j;
}
else {
return -1;
}
}
int main()
{
string str;
cout << "enter the string:";
cin >> str;
string pattern;
cout << "enter the pattern:";
cin >> pattern;
int result = KMP(str, pattern);
cout << result << endl;
}
运行结果(VS2019)
有很多情况还没有测试,如果有什么问题,欢迎一起探讨。
参考
https://blog.csdn.net/weixin_41106545/article/details/83573340
https://blog.csdn.net/crazy_scott/article/details/79211961?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task