0
点赞
收藏
分享

微信扫一扫

【YBTOJ进阶训练指导】字符串匹配【KMP】

蚁族的乐土 2022-02-16 阅读 52

在这里插入图片描述

很显然想到一种思路,把kmp的匹配模式改为当前位字符和上次出现位置的相对距离进行匹配
然后做法就很显然
同时处理一种特殊情况,如果位置差大于匹配长度时,直接视为没有出现过

c o d e code code

#include<iostream>
#include<cstring> 
#include<cstdio>
#define solve(x, y) (x<y?x:0)

using namespace std;

int t, t1;
int n, m, sum, ans[1001000];
int a[1001000], b[1001000], last[1001000];
int nxt[1001000];

void next_()
{
	nxt[1]=0;
	int k=0;
	for(int i=1; i<m; i++)
	{
		while(k&&solve(b[i+1], k+1)!=solve(b[k+1], k+1))
			k=nxt[k];
		if(solve(b[i+1], k+1)==solve(b[k+1], k+1))
			k++;
		nxt[i+1]=k;
	}
}

void kmp()
{
	int k=0;
	for(int i=1; i<=n; i++)
	{
		while(k&&solve(a[i], k+1)!=solve(b[k+1], k+1))
			k=nxt[k];
		if(solve(a[i], k+1)==solve(b[k+1], k+1))
			k++;
		if(k==m)
		{
			ans[++sum]=i-m+1;
			k=nxt[k];
		}
	}
}

int main()
{
	scanf("%d%d", &t, &t1);
	while(t--)
	{
		scanf("%d%d", &n, &m);
		for(int i=1; i<=n; i++)
		{
			int x;
			scanf("%d", &x);
			a[i]=i-last[x];
			last[x]=i;
		}
		memset(last, 0, sizeof(last));
		for(int i=1; i<=m; i++)
		{
			int x;
			scanf("%d", &x);
			b[i]=i-last[x];
			last[x]=i;
		}
		next_();
		kmp();
		printf("%d\n", sum);
		for(int i=1; i<=sum; i++)
			printf("%d ", ans[i]);
		printf("\n");
		sum=0, memset(last, 0, sizeof(last));
	}
	return 0;
}
举报

相关推荐

0 条评论