【解题思路】
此题首先容易看出是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+简单处理