KMP字符串模式匹配算法

对问题:在主串中找到子串,若找到,则返回子串首在主串中的下标 ,否则返回-1

算法核心思想是,主串中下标 不回溯,求得子串的next数组(作用就是,如果到了这个位置不匹配了,那接下来子串下标 j 该回溯到哪里),然后开始对下标为 i 的主串和下标为 j 的子串逐个匹配,遇到不匹配时,找next数组中 next[j]存放的下标,将 j 回溯到此。

PS:其实返回0也可以,因为S[0]、T[0]被用来保存字符串的长度了,真正字符串是从下标1开始的。

#include <bits/stdc++.h>
using namespace std;
void get_next(char T[], int *next)
{
	int i = 1, j = 0;
	next[1] = 0;
	while (i < T[0])//T[0]存放的是该字符串的长度,具体字符从T[1]开始
	{
		if (j == 0 || T[i] == T[j])//推到next数组
		{
			i++;
			j++;
			next[i] = j;
		}
		else
			j = next[j];
	}
}
//对next数组进行改进
void get_nextval(char T[], int *next)//对next数组进行改进
{
	int i = 1, j = 0;
	next[1] = 0;
	while (i < T[0])
	{
		if (j == 0 || T[i] == T[j])
		{
			i++;
			j++;
			if (T[i] != T[j])//遇到不同的才继续向前
				next[i] = j;
			else//遇到相同的则保存与之前相同的
				next[i] = next[j];
		}
		else
			j = next[j];
	}
}
int Index_KMP(char S[], char T[], int pos)
{
	int i = pos;
	int j = 1;
	int next[255];
	get_nextval(T, next);
	while (i <= S[0] && j <= T[0])
	{
		if (j == 0 || S[i] == T[j])
			i++, j++;
		else
			j = next[j];
	}
	if (j > T[0])
		return i - T[0];
	else return -1;
}

int main()
{
	char S[255], T[255];
	strcpy(S + 1, "AAAABCDEF");
	S[0] = strlen(S + 1);
	strcpy(T + 1, "AB");
	T[0] = strlen(T + 1);
	printf("%d\n",Index_KMP(S, T, 1));

	return 0;
}

猜你喜欢

转载自blog.csdn.net/waterboy_cj/article/details/81141989