描述
奶牛们开始对用射电望远镜扫描牧场外的宇宙感兴趣。最近,他们注意到了一种非常奇怪的脉冲调制微波从星系的中央发射出来。他们希望知道电波是否是被某些地外生命发射出来的,还是仅仅是普通的的星星发出的。
帮助奶牛们用一个能够分析他们在文件中记下的记录的工具来找到真相。他们在寻找长度在A到B之间(包含A和B本身)在每天的数据文件中重复得最多的比特序列 (1 <= A <= B <= 12)。他们在找那些重复得最多的比特序列。一个输入限制告诉你应输出多少频率最多的序列。
符合的序列可能会重叠,并且至少出现一次的序列会被计数。
格式
PROGRAM NAME: contact
INPUT FORMAT:
(file contact.in)
第一行: 三个用空格分隔的整数: A, B, N; (1 <= N < 50)
第二行及以后: 一个最多200,000字符的序列,全是0或1; 每行字符数不大于80。
OUTPUT FORMAT:
(file contact.out)
输出N个频率最高的序列(按照频率由高到低的次序)。由短到长排列频率相同的这些序列,如果长短相同,按二进制大小排列。如果出现的序列个数小于N,输出存在的序列。
对于每个存在的频率,先输出单独包含该频率的一行,再输出以空格分隔的这些序列。每行六个(除非少于六个剩下)。
SAMPLE INPUT
2 4 10 01010010010001000111101100001010011001111000010010011110010000000
在样例里,序列100出现了12次,而序列1000出现了5次。次数最多的序列是00,出现了23次。
SAMPLE OUTPUT
23 00 15 01 10 12 100 11 11 000 001 10 010 8 0100 7 0010 1001 6 111 0000 5 011 110 1000 4 0001 0011 1100
【题解】这道题可一先用字典树保存所有可能的子串。然后取出每一种子串出现的次数,放到一个数组中排个序就可以了。
/*
ID:cymxyym1
TASK:contact
LANG:C++
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
struct flag{
flag *next[2];
int cont;
char ss[15];
flag(){
next[0]=next[1]=0;
memset(ss,0,sizeof(ss));
cont=0;
}
}*f[10000];
flag *root=new flag;
struct pp{
int cont;
char c[15];
pp(){
memset(c,0,sizeof(c));
}
}w[10000];
char s[200100];
int A,B,N,len;
//建树;
inline void add(int x,int y)
{
flag *k=root;
int i=0;
while(i<y && x+i<=len){
int t=s[x+i]-'0';
if((k->next[t])==0)
{
k->next[t]=new flag;
for(int e=0;e<=i;e++)k->next[t]->ss[e+1]=s[x+e];
}
k=k->next[t];
if(i>=(A-1))k->cont++;
i++;
}
}
//排序要求
bool pan(pp x,pp y){
int i;
for(i=14;i;i--){
int a=0,b=0;
if(x.c[i]=='0'|| x.c[i]=='1')a=1;
if(y.c[i]=='0'|| y.c[i]=='1')b=1;
if(!(a+b))continue;
if((a+b)==1)return a==0?0:1;
break;
}
for(int j=1;j<=i;j++)
if(x.c[j]<y.c[j])return 0;
else if(x.c[j]>y.c[j])return 1;
}
inline bool cmp(pp x,pp y){
return x.cont==y.cont?pan(x,y):x.cont<y.cont;
}
int main()
{
freopen("contact.in","r",stdin);
freopen("contact.out","w",stdout);
scanf("%d%d%d",&A,&B,&N);
char ch;len=0;
while(scanf("%c",&ch)!=EOF)
if(ch=='0' || ch=='1')s[++len]=ch;
for(int i=1;i<=len-A+1;i++)add(i,B);
int p=0;f[1]=root;
int head=1,tail=1;
while(head<=tail){//宽搜所有子串;
flag *t=f[head++];
w[++p].cont=t->cont;
for(int e=1;e<=14;e++)w[p].c[e]=t->ss[e];
if((t->next[0])!=0)
f[++tail]=t->next[0];
if((t->next[1])!=0)
f[++tail]=t->next[1];
}
sort(w+1,w+1+p,cmp);//排序;
int time=0,i,chang;
for(i=p;i;i--)if(w[i].cont!=0){
if(w[i].cont!=w[i+1].cont || i==p){
time++;
if(time>N)break;
if(i!=p)printf("\n");
printf("%d\n",w[i].cont);
int l=1;chang=0;
while(w[i].c[l]=='0' || w[i].c[l]=='1')printf("%c",w[i].c[l++]);
}else{
chang++;
if(chang%6)printf(" ");
else printf("\n");
int l=1;
while(w[i].c[l]=='0' || w[i].c[l]=='1')printf("%c",w[i].c[l++]);
}
}
printf("\n");
return 0;
}