看毛片算法

看毛片算法

给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。\(n,m<=10^6\)

众所周知,kmp算法是需要border数组的。\(border[i]\)表示前缀i的border的位置。

注意,字符串是从0开始编号的,算法中的所有数组也都是从零开始使用的。这样能使代码更易懂~

然后两张图就能够说明一切了:第一张表示求nxt,第二张表示匹配。

图片

#include <cstdio>
#include <cstring>
using namespace std;

const int maxn=1e6+5;
char s1[maxn], s2[maxn];
int n1, n2, nxt[maxn];

int main(){
	scanf("%s", s1); scanf("%s", s2);
	n1=strlen(s1); n2=strlen(s2); 
	int j=nxt[0]=-1;  //j:i-1的border位置 
	for (int i=1; i<n2; ++i){
		for (; ~j&&s2[j+1]!=s2[i]; j=nxt[j]); ++j;
		if (!j&&s2[0]!=s2[i]) j=-1;
		nxt[i]=j;
	} j=-1;  //j:s2中已经匹配完成的位置 
	for (int i=0; i<n1; ++i){
		for (; ~j&&s2[j+1]!=s1[i]; j=nxt[j]); ++j;
		if (j==n2-1){ j=nxt[j]; printf("%d\n", i-n2+2); }
		if (!j&&s2[0]!=s1[i]) j=-1;
	}
	for (int i=0; i<n2; ++i) printf("%d ", nxt[i]+1);
	return 0;
}
posted @ 2018-06-13 20:26  pechpo  阅读(674)  评论(0编辑  收藏  举报