UESTC 1091秋实大哥の恋爱物语 【简单KMP】


【解题思路】

此题首先容易看出是KMP算法,唯一的难点在于上下平移。

我们很容易证明对于两个串A,B,如果B能够在A中匹配x次(可以上下平移),那么A和B中每一个数减去前一个数的差组成的新串匹配次数一样。

例如:

A:1 2 3 1 2 3

B:1 2

匹配次数:4

做差之后->

A:1 1 -2 1 1

B:1

匹配次数:4

所以只需要预处理一下,将模式串和匹配串都做差处理即可。


【代码】:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<ctime>
#include<cmath>
#include<iomanip>
#define LL long long
#define LOCAL
using namespace std;

const int N=2000005;
int T[N],P[N],F[N];
int posm,posn;
int cnt=0;

void Fail(int *P,int *F){
	F[0]=F[1]=0;
	for (int i=1;i<posm;++i){
		int j=F[i];
		while (j&&P[i]!=P[j]) j=F[j];
		F[i+1]=(P[i]==P[j]) ? j+1 : 0;
	}
}

void KMP(int *T,int *P,int *F){
	Fail(P,F);
	int j=0;
	for (int i=0;i<posn;++i){
		while (j&&T[i]!=P[j]) j=F[j];
		if (P[j]==T[i]) j++;
		if (j==posm){
			cnt++;
			if (cnt==1) printf("Wow! Life Winner!\n");
			j=F[j];
		}
	}
}

int main(){
#ifdef LOCAL
    freopen("UESTC1091.in","r",stdin);
#endif
	scanf("%d",&posn);
	for (int i=0;i<posn;++i) scanf("%d",&T[i]);
	for (int i=0;i<posn-1;++i) T[i]=T[i+1]-T[i];
        T[posn-1]=0;
        posn--;
	scanf("%d",&posm);
	for (int i=0;i<posm;++i) scanf("%d",&P[i]);
	for (int i=0;i<posm-1;++i) P[i]=P[i+1]-P[i];
	P[posm-1]=0;
	posm--;
	KMP(T,P,F);
	if (cnt!=0) printf("%d\n",cnt);
	else printf("Oh. That's impossible. I must have had a dream.\n");
	return 0;

}
【总结】:KMP+简单处理


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值