欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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数组的求法:

  1. j = 1时, next[j] = 0
  2. next[j] = max{k| 1<k<j, P(1)...P(k-1) == P(j-k+1)...P(j-1)
  3. 其他情况时, next[j] = 1;

 next 负责把模式串向前移动,且当第j位不匹配的时候,用第next[j]位和主串匹配,就像打了张“表”。此外,next 也可以看作有限状态自动机的状态,在已经读了多少字符的情况下,失配后,前面读的若干个字符是有用的。

KMP算法,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


相关标签: 算法 KMP