【模板】KMP

P3375 【模板】KMP字符串匹配

题目描述

如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。

为了减少骗分的情况,接下来还要输出子串的前缀数组next。

(如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了。)

输入输出格式

输入格式:

第一行为一个字符串,即为s1

第二行为一个字符串,即为s2

输出格式:

若干行,每行包含一个整数,表示s2在s1中出现的位置

接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值。

输入输出样例

输入样例#1: 
ABABABC
ABA
输出样例#1: 
1
3
0 0 1 

说明

时空限制:1000ms,128M

数据规模:

设s1长度为N,s2长度为M

对于30%的数据:N<=15,M<=5

对于70%的数据:N<=10000,M<=100

对于100%的数据:N<=1000000,M<=1000000

本着容易理解的思想学习这个算法

#include<iostream>
#include<string>
#include<stdio.h>
using namespace std;
const int maxn = 1e6;
string tex, pat;									//tex文本串  pat模式串
int nex[maxn];

void getnext(string pat, int lenpat) {				//获取nex数组
	int j = nex[0] = -1;							//j相当于记录nex[i]的值
	for (int i = 1; i < lenpat; i++) {				//求next[1]~next[len-1]
		while (j != -1 && pat[i] != pat[j + 1]) {
			j = nex[j];								//j回退,直到j回退到-1或pat[i]==pat[j+1]
		}
		if (pat[i] == pat[j+1])j++;					//相等,先令j指向这个位置。
		nex[i] = j;									//赋值给nex[i]
	}
}

int kmp(string tex, string pat) {
	int lent = tex.size(), lenp = pat.size();
	getnext(pat,lenp);									//获取模式串的nex[]数组
	int cnt = 0, j = -1;								//cnt:成功匹配次数
	for (int i = 0; i < lent; i++) {					//试图匹配tex
	//	cout << "i=	" << i << endl;
		while (j != -1 && tex[i] != pat[j + 1]) {		
			j = nex[j];									//j回退,直到j回退到-1或pat[i]==pat[j+1]
		}
		if (tex[i] == pat[j + 1])
			j++;										//匹配的话,继续
		if (j == lenp-1)
			cout << i+2-lenp<< "
",cnt++, j = nex[j];			//i下标从零开始的,应该属输出 i+1-(lenp)+1
	}
	return cnt;
}

int main() {
	cin >> tex>>pat;
	int lenp = pat.size();
	kmp(tex, pat);
	for (int i = 0; i < lenp; i++)
		cout << nex[i]+1 << " ";
	return 0;
}
原文地址:https://www.cnblogs.com/52dxer/p/10475545.html