您的位置:首页 > 其它

Sereja ans Anagrams

2014-08-06 11:04 351 查看
Codeforces Round #215 (Div. 1) B:http://codeforces.com/problemset/problem/367/B

题意:给你两个序列a,b,然后给你一个数p,然后让你在a序列中找一个位置q,得以这个位置开始,以后每隔着aq+aq+1*(p)+.......aq+(m-1)*p,这个序列经过重新排序能够等于b,输出,所有的这样的位置。

题解:可以采用递推。先找起点是1,然后再找起点是1+p,找1+p的时候,其实只要在找1的基础上删除最前的那个数,然后再加入一个数就可以了。一次类推,然后,找2开头,2+开头。具体实现的时候,可以看下面代码。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int N=4e5+10;
int a
,b
;//记录a,b,序列
int counts
,ans
;//counts统计b序列数字出现的次数
int n,m,p,cnt,top;
int main(){
while(~scanf("%d%d%d",&n,&m,&p)){
map<int,int>Qa;//离散化
memset(counts,0,sizeof(counts));
memset(a,-1,sizeof(a));
memset(b,-1,sizeof(b));
cnt=top=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(Qa[a[i]]==0)Qa[a[i]]=++cnt;
}
cnt=0;bool flag=false;
for(int i=1;i<=m;i++){
scanf("%d",&b[i]);
if(Qa[b[i]]==0){//如果b序列中数在a中没有出现,就直接不用找了
flag=true;
}
counts[Qa[b[i]]]++;//统计b中数字出现的次数
}
if(!flag){
for(int i=1;i<=p;i++){
int ct=0,sum0=0;//每次查询记录b中数字在a中出现的次数,如果出现m次,说明等于b序列
for(int j=i;j<=n*2;j+=p){//注意这里是j<=2*n,虽然在n+1以后的数不会构成b序列,但是这里是为了把之前加入放入数都还原,便于下一次使用
counts[Qa[a[j]]]--;//入队之后次数减一
ct++;
if(counts[Qa[a[j]]]>=0)//如果次数在-1的基础上任然大于0,说明,这个数字是b中的数字
sum0++;//注意判断是要求大于0的,因为b的数字可能会重复
if(ct==m){//判断第一次达到m个数是否满足条件
if(sum0==m)
ans[++top]=i;
}
else if(ct>m){//当多余m个时候,就要把最前面的数删除,只保留m个数
if(counts[Qa[a[i+(ct-1-m)*p]]]>=0){//如果这个数次数大于=0,说明这个数被统计过,所以要还原
sum0--;
counts[Qa[a[i+(ct-1-m)*p]]]++;
}
else{
counts[Qa[a[i+(ct-1-m)*p]]]++;
}
if(sum0==m){//判断新加入过的数有没有满足条件
ans[++top]=i+(ct-m)*p;
}
}
}
}
}
sort(ans+1,ans+top+1);
printf("%d\n",top);
for(int i=1;i<top;i++)
printf("%d ",ans[i]);
if(top>0)
printf("%d\n",ans[top]);
else
printf("\n");
}
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: