题目链接:
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1794
题目是问两个钟能否重合,考虑将数据读入后排序,之后作差产生新的序列(注意作差的时候要作N个,即最后一个与第一个之间的差也要做上,否则会WA)
产生的两个差序列进行匹配就可以,有两种方法,首先想到的是循环KMP,将一个序列复制一遍用另一个序列进行匹配就可以。
代码如下:
(这道题在做的过程中还出现了一些小问题,对于OJ上面读入使用while(scanf()!=EOF)或者while(~scanf()),而使用while(scanf())有可能会造成TLE)
#include<iostream>
#include<cstdio>
#include<cstring>
#include"algorithm"
using namespace std;
const int maxn=400000+10;
int numa[maxn],numb[maxn];
int fail[maxn],a[maxn],b[maxn];
int n;
const int modd=360000;
void getfail()
{
memset(fail,0,sizeof(fail));fail[0]=-1;
for(int i=1;i<n;i++)
{
int p=fail[i-1];
while(p>=0&&a[p+1]!=a[i])p=fail[p];
fail[i]=p+1;
}
}
int main()
{
while(~scanf("%d",&n))
{
int flag=0;
for(int i=0;i<n;i++)
{
scanf("%d",&numa[i]);
}
for(int i=0;i<n;i++)
{
scanf("%d",&numb[i]);
}
sort(numa,numa+n);
sort(numb,numb+n);
numa[n]=numa[0];
numb[n]=numb[0];
for(int i=1;i<=n;i++)
{
a[i]=(numa[i]-numa[i-1]+modd)%modd;
b[i]=(numb[i]-numb[i-1]+modd)%modd;
}
getfail();
for(int i=n+1;i<=2*n;i++)
b[i]=b[i-n];
for(int i=1,p=0;i<=n*2;i++)
{
while(p>=0&&a[p+1]!=b[i])p=fail[p];
if(++p==n){flag=1; break;}
}
if(flag) cout<<"possible"<<endl;
else cout<<"impossible"<<endl;
}
}
另一种方法是参考大神的博客学习的,如果两个字符串能够匹配(在这个题目中应该叫做循环同构),那么他们的最小表示法是相同的,这是个充要条件。关于同样题目的解释,我找到了一个比较清楚的博客
那么我们只需要判断两个复制后的字符串的最小表示法是否相同就可以了
具体代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include"algorithm"
using namespace std;
const int maxn=400000+10;
int numa[maxn],numb[maxn];
int fail[maxn],a[maxn],b[maxn];
int n;
const int modd=360000;
int main()
{
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)
{
scanf("%d",&numa[i]);
}
for(int i=0;i<n;i++)
{
scanf("%d",&numb[i]);
}
sort(numa,numa+n);
sort(numb,numb+n);
numa[n]=numa[0];
numb[n]=numb[0];
for(int i=1;i<=n;i++)
{
a[i+n]=a[i]=(numa[i]-numa[i-1]+modd)%modd;
b[i+n]=b[i]=(numb[i]-numb[i-1]+modd)%modd;
}
int i,j,k;
for(i=1,j=1;i<=n&&j<=n;)
{
for(k=0;k<n;k++)
{
if(a[i+k]>b[j+k])
{
i+=k+1;
break;
}
else if(a[i+k]<b[j+k])
{
j+=k+1;
break;
}
}
if(k==n) break;
}
if(k==n) cout<<"possible"<<endl;
else cout<<"impossible"<<endl;
}
return 0;
}