KMP算法,next数组详解

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 也可以看作有限状态自动机的状态,在已经读了多少字符的情况下,失配后,前面读的若干个字符是有用的。


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


猜你喜欢

转载自blog.csdn.net/shidamowang/article/details/80347624