/*
实现效果:输出每一个能在父串中找到的子串的匹配起始下标
eg:
输入:
son:aba
parent:ababa
输出:
0 2(下标从0开始匹配aba,从2开始匹配aba)
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10,M = 1e6 + 10;
int sonLength,parentLength;//子串长度,父串长度
int Next[N];//Next数组
char son[M],parent[N];//子串,父串
int main()
{
//依次输入子串长度,子串,父串长度,父串
//注意:下标从1开始输入,略过0
cin >> sonLength >> son + 1 >> parentLength >> parent + 1;//son[1] = a,par[1] = a
//开始匹配,给Next数组赋值
for(int i = 2,j = 0;i <= sonLength;i++){//遍历子串
while(j && son[i] != son[j + 1])j = Next[j];//元素不同,Next指针回退
if(son[i] == son[j + 1])j ++;//遇到相同元素,Next指针后移
Next[i] = j;//给定每一个子串字符赋予Next值
}
/*
模拟过程:以aba,ababa举例
1. j = 0,i = 2,判断while,j不存在,直接略过while,
此时判断son[2]与son[1]不相同,Next[2] = 0
2. j = 0,i = 3,判断while,同理略过while,
判断son[3]与son[1]相等,j = 1,Next[3] = 1;
3. i已经达到3,for循环结束
//该部分只对子串部分进行判断,并生成Next数组,不涉及父串
*/
for(int i = 1,j = 0;i <= parentLength;i++){
while(j && parent[i] != son[j + 1])j = Next[j];//Next指针回退
if(parent[i] == son[j + 1])j ++;//确定匹配就匹配下一个,即j + 1
if(j == sonLength){//在父串中找到子串
printf("%d ",i - sonLength);//子串起始下标
j = Next[j];//指针回退,准备下一次匹配
}
}
/*
模拟过程: 父串ababa 子串aba
1. i = 1,j = 0,j = 0,略过while,parent[1]:a与son[1]: a匹配,相等,
j = 1,j != 3
2. i = 2,j = 1,parent[2]:b,son[2]:b,相等,略过while,
parent[2]:b,son[2]:b,j = 2,j != 3
3. i = 3,j = 2,parent[3]:a,son[3]:a,相等,略过while,
j = 3等于sonLength,输出起始下标3 - 3 = 0,j = Next[3] = 1
4. i = 4,j = 1,parent[4]:b与son[2]:b相等,j = 2 != 3
5. i = 5,j = 2,parent[5]:a与son[3]:a相等,略过while,
j = 3等于sonLength,输出起始下标5 - 3 = 2,j = Next[3] = 1
6. i已到达6,停止for。
*/
return 0;
}
[算法][笔记]KMP详解-模拟
最新推荐文章于 2022-08-04 10:51:54 发布