CDOJ 1091 秋实大哥の恋爱物语 KMP

给两个数字串A和B

判断能否使B的每一个数能经过加或减某一整数,与A的某一段重合。

当时做的时候,刚刚了解KMP,想了很久也不知道该怎么做,还是听了讲解之后才知道。

需要处理一下,因为B能加减某一个数,所以不能枚举加减哪个数,但是B究竟应该和A的第几个开头的子串重合呢,也无法枚举。

然后,,,只需要存储B的每一个数与前一个数的差(第一个数除外),然后A也如此存储。这样,去匹配就好,因为,只要他们每个与前一个的差一样,那么他们肯定是整体都只差一个数。想想确实是这样。。。。


代码:

#include <iostream>
#include <cstdio>
using namespace std;
#define maxn 2000005
int S[maxn] = { 0 };
int T[maxn] = { 0 };
int SS[maxn] = { 0 };
int TT[maxn] = { 0 };
int then[maxn] = { 0 };
int cnt = 0;
void get_then()
{
	int i = 1, j = 0;
	then[1] = 0;
	while (i <= TT[0])
	{
		if (j == 0 || TT[i] == TT[j])
		{
			++i; ++j; then[i] = j;
			//printf("i%d\tthen%d\t", i, then[i]);
		}
		else j = then[j];
	}
}
void KMP(int pos)
{
	int i = pos-1, j = 0;
	while (i <= SS[0])
	{
		if (j == 0 || SS[i] == TT[j])
		{
			++i; ++j;
		}
		else j = then[j];
		if (j > TT[0])
		{
			cnt++; 
			j = then[j];
			//printf("%d\t", i-1);
		}
	}
}
int main()
{
	scanf("%d", &S[0]); SS[0] = S[0] - 1;
	for (int i = 1; i <= S[0]; i++)
	{
		scanf("%d", &S[i]);
		if (i > 1) SS[i - 1] = S[i] - S[i - 1];
	}
	scanf("%d", &T[0]); TT[0] = T[0] - 1;
	for (int i = 1; i <= T[0]; i++)
	{
		scanf("%d", &T[i]);
		if (i > 1) TT[i - 1] = T[i] - T[i - 1];
	}
	//for (int i = 1; i <= SS[0]; i++)
		//printf("%d\t", SS[i]);
	//printf("换行\n");
	get_then();
	//printf("换行\n");
	KMP(1);
	//printf("\n");
	if (cnt == 0)
		printf("Oh. That's impossible. I must have had a dream.");
	else
		printf("Wow! Life Winner!\n%d", cnt);
	//while (1);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值