给两个数字串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;
}