kmp 学习【字符串-kmp学习】

最近学算法,了解了一些好玩的东西。
KMP算法(Knuth-Morris-Pratt)的K的指的是计算机大佬 高德纳
大神就是大神,人生经历牛逼。
昨天在看舞蹈链的知识(也是高德纳大神发明的୧(๑•̀◡•́๑)૭)

分析

为了能够理解AC自动机,我又看起了KMP,这个KMP最难理解的还是next数组
就是那一句k=next[k],太难理解了。
写的话还是能把KMP写出来的。
首先写暴力算法,在暴力算法的基础上写出kmp算法,至于get_next()结构和kmp算法很想,再此基础上略微改变就行。

kmp算法通过取消了主串的回溯,来加快算法。
因为有一些比较是多余的,可以通过模式串的结构来简化这个过程。
next数组的一个核心概念就是前缀和后缀。
它求的是一个字符串的相同的最大前缀和最大后缀的长度。

至于以前一直困扰我的next数组赋值的问题,最近想明白了,其实他们是一致的,多1少1无非是为了程序好写。

My Code

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1e6+5;

int NEXT[maxn];
int bf(char* source,char *pattern )
{
	int n=strlen(source);
	int m=strlen(pattern);
	int i=0;
	int j=0;
	while(i<n&&j<m)
	{
		if(source[i]==pattern[j])
		{
			i++;
			j++;
		}
		else
		{
			i=i-j+1;
			j=0;			
		}
	}
	if(j==m)
		return i-j;
	else
		return -1;
}

int kmp(char* source,char *pattern )
{
	int n=strlen(source);
	int m=strlen(pattern);
	int i=0;
	int j=0;
	while(i<n&&j<m)
	{
		if(j==-1||source[i]==pattern[j])
		{
			i++;
			j++;
		}
		else
		{
			j=NEXT[j];
		}
	}
	if(j==m)
		return i-j;
	else
		return -1;
}


void GetNext(char* pattern)
{
	int pLen = strlen(p);
	NEXT[0] = -1;
	int k = -1;
	int j = 0;
	while (j < pLen - 1)
	{
		//p[k]表示前缀,p[j]表示后缀
		if (k == -1 || p[j] == p[k]) 
		{
			++k;
			++j;
			NEXT[j] = k;
		}
		else 
		{
			k = NEXT[k];
		}
	}
}



int main()
{
	/*
	// 指针初始化 字符串常量, 内存分配在全局的const内存区,需要加上const
	char* source="BBC ABCDAB ABCDABCDABDE";	
	char* pattern="ABCDABD";
	
	// 正确的初始化操作
	char* source="BBC ABCDAB ABCDABCDABDE";
	char* pattern="ABCDABD";
	
	char source[]="BBC ABCDAB ABCDABCDABDE";
	char pattern[]="ABCDABD";
	*/
	char source[]="BBC ABCDAB ABCDABCDABDE";
	char pattern[]="ABCDABD";	
	printf("%s
",source);
	printf("%s
",pattern);
	cout<<bf(source,pattern)<<endl;
	GetNext(pattern);
	cout<<kmp(source,pattern)<<endl;;
    return 0;
}
原文地址:https://www.cnblogs.com/shengwang/p/9779449.html