KMP算法,next数组详解
程序员文章站
2024-02-16 09:26:52
...
next数组(a) - 除当前字符外,最长相同前缀后缀
最大长度值(b) - 最大对称长度的前缀后缀
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
匹配字符串 | a | b | c | d | a | b | c | x |
next数组(a) | 0 | 1 | 1 | 1 | 1 | 2 | 3 | 4 |
最大长度值(b) | 0 | 0 | 0 | 0 | 1 | 2 | 3 | 0 |
变化最大长度值(c) | -1 |
0 | 0 | 0 | 0 | 1 | 2 | 3 |
next数组的求法:
- j = 1时, next[j] = 0
- next[j] = max{k| 1<k<j, P(1)...P(k-1) == P(j-k+1)...P(j-1)
- 其他情况时, next[j] = 1;
next 负责把模式串向前移动,且当第j位不匹配的时候,用第next[j]位和主串匹配,就像打了张“表”。此外,next 也可以看作有限状态自动机的状态,在已经读了多少字符的情况下,失配后,前面读的若干个字符是有用的。
next数组和最大长度值的联系:最大长度值向右平移一位,并且初始值赋为 -1,形成变化最大长度值
此时相当于编号为 0-7 的匹配字符串next数组,next数组(a)是编号为 1-8 。
#include<iostream>
#include"string.h"
using namespace std;
void getNext(char*, int*);
void get_next(char*, int*);
int index_kmp(char* , char* , int);
int index_kmp2(char*, char*, int);
int main()
{
char t_a[] = "8abcdabcx";
char t_c[] = "abcdabcx";
char s[] = "ddabcdabcxeifcc";
cout << index_kmp(s, t_a, 0) << endl; //next数组(a),第一种情况
cout << index_kmp2(s, t_c, 0); //变化最大长度值(c),第三种情况
}
int index_kmp2(char* s, char* t, int pos)
{
int i = pos;
int j = -1;
int next[225];
getNext(t, next);
for(int i = 0; i < strlen(t); i++)
cout << next[i] << " ";
cout << endl;
int t_len = strlen(t);
while(i < strlen(s) && j < t_len)
{
if(j == -1 || s[i] == t[j])
{
++i;
++j;
}
else
j = next[j];
}
if(j >= strlen(t))
return i - strlen(t);
else
return 0;
}
int index_kmp(char* s, char* t, int pos)
{
int i = pos;
int j = 1;
int next[225];
get_next(t, next);
for(int i = 1; i < strlen(t); i++)
cout << next[i] << " ";
cout << '\n';
while(i < strlen(s) && j < strlen(t))
{
if(j == 0 || s[i] == t[j])
{
++i;
++j;
}
else
j = next[j];
}
if(j >= strlen(t))
return i - strlen(t) + 1;
else
return 0;
}
void getNext(char* t, int* next)
{
int len = strlen(t);
next[0] = -1;
int i = 0;
int j = -1;
while(i < len - 1)
{
if(j == -1 || t[i] == t[j])
{
++i;
++j;
next[i] = j;
}
else
j = next[j];
}
}
void get_next(char* t, int* next)
{
int i, j;
i = 1;
j = 0;
next[1] = 0;
while(i < strlen(t))
{
if(j == 0 || t[i] == t[j])
{
++i;
++j;
next[i] = j;
}
else
j = next[j];
}
}
为了保证匹配字符串是符合从 1- 8编号,t_a[0]表示匹配字符串长度
第一种情况输出,next数组(a), 0 1 1 1 1 2 3 4
第二种情况输出,变化最大长度(c), -1 0 0 0 0 1 2 3
上一篇: Mysql如何准确赛选(排序)出最值得推荐的信息?
下一篇: Oracle 01090问题如何解决