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+簡單處理


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章