您的位置:首页 > 产品设计 > UI/UE

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

2017-03-21 17:12 381 查看




【解题思路】

此题首先容易看出是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
,P
,F
;
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+简单处理
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: