扩展KMP算法模板

Description

\(txt\)为文本串,\(pat\)为模式串。

\(nxt[i]\): \(pat[i:]\)\(pat[]\)的最长公共前缀的长度。
\(ext[i]\): \(txt[i:]\)\(pat[]\)的最长公共前缀的长度。

\(pre\_kmp(pat)\):模式串与模式串自己匹配,得到\(nxt[]\)数组。
\(ext\_kmp(txt,pat)\):求\(nxt[]\)\(pat[]\)数组。

Input

第一行给出文本串\(txt\),第二行给出模式串\(pat\)

Output

输出\(ext[]\)数组。

Sample Input

abaabaab
aaba

Sample Output

1 0 4 1 0 3 1 0 

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e3 + 10;

int nxt[N], ext[N];

void pre_kmp(char pat[])
{
    int lpat = strlen(pat);
	nxt[0] = lpat;
	int j = 0;
	while (j + 1 < lpat && pat[j] == pat[j + 1]) j++;
	nxt[1] = j;
	for (int i = 2, k = 1; i < lpat; i++)
	{
		int p = nxt[k] + k - 1;
		int l = nxt[i - k];
		if (i + l < p + 1) nxt[i] = l;
		else
		{
			j = max(0, p - i + 1);
			while (i + j < lpat && pat[i + j] == pat[j]) j++;
			nxt[i] = j;
			k = i;
		}
	}
}

void ext_kmp(char txt[], char pat[])
{
    pre_kmp(pat);
    int ltxt = strlen(txt);
    int lpat = strlen(pat);
	int j = 0;
	while (j < ltxt && j < lpat && pat[j] == txt[j]) j++;
	ext[0] = j;
	for (int i = 1, k = 0; i < ltxt; i++)
	{
		int p = ext[k] + k - 1;
		int l = nxt[i - k];
		if (i + l < p + 1) ext[i] = l;
		else
		{
			j = max(0, p - i + 1);
			while (i + j < ltxt && j < lpat && txt[i + j] == pat[j]) j++;
			ext[i] = j;
			k = i;
		}
	}
}

char txt[N], pat[N];

int main()
{
    scanf("%s%s", txt, pat);
    ext_kmp(txt, pat);
    int len = strlen(txt);
    for (int i = 0; i < len; i++) printf("%d ", ext[i]);
    return 0;
}
posted @ 2017-08-17 20:26  达达Mr_X  阅读(127)  评论(0编辑  收藏  举报