先进型(nextval+自适应长度,支持多序列捕获)
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int N = 1e5 + 10;
string a, b; //主串a,子串b
int v[N];
void init()
{
system("cls");
printf("输入子串:"), cin >> b;
printf("输入主串:"), cin >> a;
printf("b.size=%d a.size=%d\n", b.size(), a.size());
}
void work()
{
for (int x = 0, y = 1; y < b.size();)
{ //此处xy都是【具体位置】、不是、存储位置
if (x == 0 || b[x - 1] == b[y - 1])
{
x++, y++;
v[y] = b[x - 1] != b[y - 1] ? x : v[x]; //不相同写x,相同写v[x]
}
else
x = v[x]; //对【前端匹配】进行【自回溯】
}
}
void show()
{
printf("Nextval:");
for (int x = 1; x <= b.size(); x++)
printf("%d ", v[x]);
printf("\n");
}
void use()
{
int x = 1, y = 1;
while (x <= a.size() - b.size() + 1)
{
while (x <= a.size() && y <= b.size())
{
if (y == 0 || a[x - 1] == b[y - 1])
x++, y++;
else
y = v[y]; //对子串进行回溯
}
x -= b.size();
if (x <= a.size() - b.size() + 1 && y == b.size() + 1)
printf("捕获位置:%d\n", x);
y = 1, x += b.size();
}
}
int main()
{
init();
work();
show();
use();
return 0;
}
/*
ababaaaba
abbababaaabbababaaabababbababaaabaaabb
ababaaaba
abbababaaabbababaaabababbaabbababaaaba
ababaaaba
abbababaaabbababaaabababbaabbababaaabc
*/
综合型
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define MAXX 500
char a[MAXX], b[MAXX];
int n[MAXX] = {}, v[MAXX] = {};
void init()
{
printf("【KMP算法测试】鸿蒙·乾坤 Day213\n");
printf("输入【主串A】:");
scanf("%s", &a);
printf("输入【子串B】:");
scanf("%s", &b);
printf("【主串A】长度%d\t\t%s\n", strlen(a), a);
printf("【子串B】长度%d\t\t%s\n", strlen(b), b);
printf("\n");
}
void show()
{
printf("Next\t\tNextvla\n");
for (int x = 1; x <= strlen(b); x++)
{
printf("%d\t\t%d\n", n[x], v[x]);
}
printf("\n");
}
void nextval()
{
printf("\n\nNEXTVAL匹配测试\n");
int x = 1, y = 1;
// printf("从【主串】第几个数字开始匹配:");
// scanf("%d", &x);
while (y <= strlen(b) && x <= strlen(a)) // a主串,b子串
{
if (a[x - 1] == b[y - 1] || y == 0)
{
x++;
y++;
}
else
{
y = v[y];
}
printf("主串-子串:%d %d\n", x, y);
// system("pause");
}
if (x <= strlen(a)) //主串没有溢出,说明匹配成功
printf("\n起始位置%d\n", x - strlen(b));
else
printf("\n匹配失败\n");
}
void work()
{
int x = 0, y = 1;
// x:当前最长公共子序列,=0时候表示溢出
// y:next部署的前一个数值
while (y < strlen(b)) // y==11进来,可以生成y=12的n/v
{
printf("公共长度-匹配坐标:%d %d\n", x, y);
if (x == 0 || b[x - 1] == b[y - 1]) //相同,或者溢出
{ // x=0是溢出情况;x+1复位,y+1下一个数
x++;
y++; //此处x就是next[y],y是当前指针位置
n[y] = x; //溢出时,下次从头匹配(1)
v[y] = b[x - 1] != b[y - 1] ? x : v[x];
//不相同时候存【当前最长公共子序列】
//否则存【回溯点】
}
else
x = v[x]; //也可以用next回溯
}
show();
}
int main()
{
init();
work(); //精准·得出next+nextval数组
// next应用 把nextval数组换成next即可,这个不如nextval先进
nextval(); // nextval应用
return 0;
}
/*
巧喑姐姐最可爱!
ababaaababaa
巧喑姐姐超可爱!
ababaaaba
ababaaababaa
aaba
*/