CSU1581 Clock Pictures
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=158915
题意:分别给出两个钟表上针的位置,判断是否可以通过旋转使两个钟表相等
思路:KMP。存储两个钟表的相邻指针差值的数组,任选一个数组作为模式串Fail,另一个作为比较串。由于会循环比较,直接把比较串扩展成原来两倍,新增部分为原来串的重复。(比如1 2 扩展成1 2 1 2),然后就结束了。
求差值的时候没有考虑最后使用a[0]时a[0]已经变了,WA.....
源码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
#define rep(i,s,n) for(int i=s; i<n; i++)
#define mod 360000
int const MAXN = 200000+5;
int t1[MAXN],t2[MAXN*2];
int ss[MAXN],fail[MAXN],n;
void init(int a[])
{
rep(i,0,n)
scanf("%d",&a[i]);
sort(a,a+n);
int temp = a[0];
rep(i,0,n-1)
a[i] = a[i+1] - a[i];
a[n-1] = (temp - a[n-1] + 360000)%mod;
}
void lin(int a[],int b[])
{
for(int i=0; i<n; i++)
a[i+n] = b[i];
}
void failure(int t[],int f[])
{
f[0] = 0;
int j = f[0];
for(int i=1; i<n; i++){
while(j>0 && t[j] != t[i]) j = fail[j-1];
if(t[j]==t[i]) j++;
fail[i] = j;
}
}
bool match(int t1[],int t2[],int *f)
{
int l1 = n;
int l2 = 2*n;
// printf("n = %d,m = %d\n",n,m);
int j = 0;
int i = 0;
while(i + l1 - j <= l2){
// printf("f i = %d,j = %d\n",i,j);
if(j==l1)
return true;
while(j && t1[j]!=t2[i]) j = fail[j-1];
if(t1[j]==t2[i]){
j++; i++;
}
else
i++;
// printf("s i = %d,j = %d\n",i,j);
}
return false;
}
int main()
{
scanf("%d",&n);
init(t1);
init(t2);
lin(t2,t2);
failure(t1,fail);
// for(int i=0; i<n; i++)
// printf("%d ",fail[i]);
// printf("\n");
if(match(t1,t2,fail))
printf("possible\n");
else
printf("impossible\n");
return 0;
}