字符串匹配的KMP算法 - 阮一峰的网络日志 (ruanyifeng.com)http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html没接触过kmp可以先看看这个👆
例题:
输入样例:
3
aba
5
ababa
输出样例:
0 2
代码实现:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5+10, M = 1e6+10;
int n, m;
int ne[N];
char s[N], g[M];
int main()
{
cin >> n >> s + 1 >> m >> g + 1;
//模式串自匹配,初始化偏移数组ne[]
for(int i = 2, j = 0; i <= n; i ++)
{
while(j && s[j+1] != s[i]) j = ne[j];
if(s[j+1] == s[i]) j ++;
ne[i] = j;
}
//两串匹配
for(int i = 1, j = 0; i <= m; i ++)
{
while(j && s[j+1] != g[i]) j = ne[j];
if(s[j+1] == g[i]) j ++;
if(j == n)
{
cout << i-n << " "; //题意中下标从0开始,因此(i-n+1)-1
j = ne[j];
}
}
return 0;
}
下面我们输出关键的ne[ ]数组(即最长前后缀匹配表)初始化的步骤
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5+10, M = 1e6+10;
int n, m;
int ne[N];
char s[N], g[M];
int main()
{
cin >> n >> s + 1 >> m >> g + 1;
//模式串自匹配,初始化偏移数组ne[]
for(int i = 2, j = 0; i <= n; i ++)
{
cout << "-----------" << endl;
while(j && s[j+1] != s[i]){
printf("s[j(%d)+1] != s[i(%d)] 👉'%c' != '%c'\n", j, i, s[j+1], s[i]);
j = ne[j];
printf("j = ne[j] (ne[%d]) = %d\n", j, ne[j]);
}
if(s[j+1] == s[i]){
printf("s[j(%d)+1] == s[i(%d)] 👉'%c' != '%c'\n", j, i, s[j+1], s[i]);
j ++;
printf("j++, j = %d\n", j);
}
ne[i] = j;
printf("ne[i(%d)] = j(%d)\n", i, j);
}
cout << "-----------" << endl;
for(int i = 1; i <= n; i ++) cout << ne[i] << " ";
cout << "#" << endl;
//两串匹配
// for(int i = 1, j = 0; i <= m; i ++)
// {
// while(j && s[j+1] != g[i]) j = ne[j];
// if(s[j+1] == g[i]) j ++;
// if(j == n)
// {
// cout << i-n << " ";
// j = ne[j];
// }
// }
return 0;
}
测试输入:
10
ababcabcab
14
abababababccba
(注: 字符串下标从1开始)
s[] | a | b | a | b | c | a | b | c | a | b |
ne[] | 0 | 0 | 1 | 2 | 0 | 1 | 2 | 0 | 1 | 2 |
下标 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
对比参照输出:
(括号内表示的是i / j此时的值)
----------- ne[i(2)] = j(0) ----------- s[j(0)+1] == s[i(3)] 👉'a' == 'a' j++, j = 1 ne[i(3)] = j(1) ----------- s[j(1)+1] == s[i(4)] 👉'b' == 'b' j++, j = 2 ne[i(4)] = j(2) ----------- s[j(2)+1] != s[i(5)] 👉'a' != 'c' j = ne[j(0)] = 0 ne[i(5)] = j(0) ----------- s[j(0)+1] == s[i(6)] 👉'a' == 'a' j++, j = 1 ne[i(6)] = j(1) ----------- s[j(1)+1] == s[i(7)] 👉'b' == 'b' j++, j = 2 ne[i(7)] = j(2) ----------- s[j(2)+1] != s[i(8)] 👉'a' != 'c' j = ne[j(0)] = 0 ne[i(8)] = j(0) ----------- s[j(0)+1] == s[i(9)] 👉'a' == 'a' j++, j = 1 ne[i(9)] = j(1) ----------- s[j(1)+1] == s[i(10)] 👉'b' == 'b' j++, j = 2 ne[i(10)] = j(2) ----------- 0 0 1 2 0 1 2 0 1 2 #