Контакт
http://acm.pku.edu.cn/JudgeOnline/problem?id=1174
Доктор Астро Ински (Astro Insky) работает в радиотелескопическом центре. Недавно она заметила очень странное пульсирующее микроволновое излучение, исходящее непосредственно из центра галактики. Посланы ли эти сигналы какой-нибудь внеземной формой разумной жизни? Или это простое сердцебиение звезд?
Вы должны помочь доктору Ински отыскать истину, создав инструмент для анализа битовых последовательностей в записанных ею сообщениях. Доктор Ински хочет найти битовые подпоследовательности длиной от А до В включительно, которые встречаются в записанной последовательности наиболее часто. Подпоследовательности могут перекрываться. Определяются N наибольших различных частот (т.е. количество вхождений). Учитываются подпоследовательности, которые встречаются хотя бы один раз.
Входные данные
Стандартный вход содержит данные в следующем формате:
В первой строке находится число А - минимальная длина подпоследовательности.
Во второй строке находится число В - максимальная длина подпоследовательности.
В третьей строке задано число N - количество различных частот вхождения.
В четвертой задано саму полученную последовательность, состоящую из символов 0 и 1, символ 2 - признак окончания сообщения.
Размер входных данных не превышает 2 Мбайта. Параметры A, B и N имеют такие ограничения:
0 < N <= 20
0 < A <= B <= 12.
Выходные данные
Вы должны вывести не более N строк, каждая из которых содержит одну из N наибольших частот вхождения и соответствующие ей подпоследовательности. Строки должны располагаться в порядке убывания частот вхождения и иметь следующий вид:
частота подпоследовательность подпоследовательность ... подпоследовательность.
Частота - это количество вхождений указанных далее подпоследовательностей. Подпоследовательности в каждой строке должны располагаться в порядке убывания длины. Подпоследовательности одинаковой длины должны располагаться в порядке убывания их числового значения. Если в последовательности встречается менее N различных частот, то выходные данные будут содержать менее N строк
Пример входных данных
2
4
10
010100100100010001111011000010100110011110000100100111100100000002
Пример выходных данных
23 00
15 10 01
12 100
11 001 000 11
10 010
8 0100
7 1001 0010
6 0000 111
5 1000 110 011
4 1100 0011 0001
Анализ условия и разбор идеи решения
Пример решения на Pascal:
program Contact;
const MAXPAT = 16;
SIZE = 2*4096;
type Pair =
record
index:integer;
val:Longint;
end;
TMap =array[0..SIZE-1] of Pair;
var table:TMap;
MSK :array[0..MAXPAT] of Word;
procedure InitPatternTable;
var i,p:word;
begin
p := 0;
for i:=0 to MAXPAT-1 do
begin
p := p shl 1;
p := p or 1;
MSK[i]:=p;
end;
for i:=0 to SIZE-1 do
begin
table[i].index:=i;
table[i].val:=0;
end;
end;
procedure PrintPattern(var i:integer);
var s:array[0..MAXPAT-1] of char;
j,l:integer;
begin
for j:=1 to MAXPAT-1 do
begin
l := MAXPAT-(j+1);
if (i and 1)<>0 then
s[l]:='1'
else s[l]:='0';
i:= i shr 1;
end;
j := 0;
while(s[j]<>'1') do inc(j);
inc(j); (* remove leading 1 *)
while(j<MAXPAT-1) do
begin
write(s[j]);
inc(j)
end;
end;
function LT(a,b:Pair):boolean;
begin
if(a.val = b.val) then
LT := a.index < b.index
else LT := a.val < b.val
end;
procedure Quicksort(loBound : integer ;
hiBound : integer );
var loSwap, hiSwap: integer;
pivot, temp: Pair;
begin
if (loBound >= hiBound) then (* Zero or one item to sort *)
exit;
if (hiBound-loBound = 1) then
begin (* Two items to sort *)
if LT(table[loBound] ,table[hiBound]) then
begin
temp := table[loBound];
table[loBound] := table[hiBound];
table[hiBound] := temp;
end;
exit;
end;
pivot := table[(loBound+hiBound) div 2]; (* 3 or more items to sort *)
table[(loBound+hiBound) div 2] := table[loBound];
table[loBound] := pivot;
loSwap := loBound + 1;
hiSwap := hiBound;
repeat
while (loSwap <= hiSwap) and NOT LT(table[loSwap],pivot)
do inc(loSwap);
while LT(table[hiSwap],pivot)
do dec(hiSwap);
if (loSwap < hiSwap) then
begin
temp := table[loSwap];
table[loSwap] := table[hiSwap];
table[hiSwap] := temp;
end;
until (loSwap >= hiSwap);
table[loBound] := table[hiSwap];
table[hiSwap] := pivot;
Quicksort(loBound, hiSwap-1);
Quicksort(hiSwap+1, hiBound);
end; (* Quicksort *)
procedure MakeListing(M:integer; L:integer;N:integer);
label done;
var T,i,lm:integer;
c:LongInt;
begin
T := MSK[L]+1;
QuickSort(MSK[M-1]+1,MSK[L]);
i:=MSK[M-1]+1;
lm:=0;
while (lm<N) and (table[i].val<>0) do
begin
c := table[i].val;
write(c,' ');
while table[i].val = c do
begin
PrintPattern(table[i].index);
inc(i);
if table[i].val = c then
write(' ')
else writeln;
if i=T then goto done;
end;
inc(lm);
end;
done:;
end;
procedure ProcessFile(var M:integer; L:integer; T:integer);
var i,mask,p,mu,pp,li:word;
ch:char;
b:longInt;
goon:boolean;
begin
p := 0;
b := 0;
{ Set the bitmask for pattern length }
mask := MSK[L+1];
{ Init with first M bits }
while b<M do
begin
read(ch);
inc(b);
p := p shl 1;
if ch='1'
then p := p or 1;
end;
{ b = M }
{ update "first" table position }
mu := MSK[M-1];
pp := mu+1+(p and mu);
table[pp].val:=1;
goon := true;
while goon do
begin
read(ch);
if ch='2' then goon := false
else
begin
inc(b);
{ update current pattern }
p := p shl 1;
if ch = '1' then p := p or 1;
p := p and mask;
if b <= L then li := b else li := L;
{ update all preceeding table positions }
for i:=M-1 to li-1 do
begin
mu := MSK[i];
pp := mu+1+(p and mu);
inc(table[pp].val);
end;
end;
end;
end;
procedure Scan;
var M,L,T : integer;
f : text;
begin
InitPatternTable;
readln(M);
readln(L);
readln(T);
ProcessFile(M,L,T);
MakeListing(M,L,T);
end;
begin
Scan;
end.Пример решения на GnuC++
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MaxLen = 2010000;
char str[MaxLen];
int N,A,B,Len,cnt;
int Arr[100000];
typedef struct re{
int num,len,time;
}re;
bool operator <(const re& a,const re& b){
if(a.time > b.time) return true;
if(a.time == b.time){
if(a.len > b.len) return true;
else if(a.len == b.len){
if(a.num > b.num) return true;
else return false;
}else return false;
}else return false;
}
re R[100000];
int input(){
scanf("%d%d",&A,&B);
scanf("%d",&N);
getchar();
char tmp;
int i = 0 ;
while(tmp = getchar()){
if(tmp == '2') break;
else str[i++] = tmp;
}
return i;
}
int Insert(char* s,int len){
int i = 1;
for(int j = 0 ;j < len; ++j){
if(s[j] == '0')
i <<=1;
else i = (i << 1) + 1;
}
++Arr[i];
}
void work(){
for(int i = A; i <= B; ++i)
for(int j = 0 ;j <= Len - i; ++j)
Insert(str + j,i);
}
void print(int num,int len){
char tmp[20];
int t = 0;
while(t < len){
if(num & 1) tmp[len - t-1] = '1';
else tmp[len - t -1] = '0';
++t;
num >>=1;
}
for(int i = 0 ;i <len; ++i)
putchar(tmp[i]);
putchar(' ');
}
void calc(){
int down = (1 << A);
int up = (1 << ( B + 1));
for(int len = A; len <= B; ++len){
for(int i = (1 << len);i < (1<<(len+1)); ++i){
if(Arr[i] != 0){
R[cnt].num = i; R[cnt].len = len; R[cnt].time = Arr[i];
++cnt;
}
}
}
}
int main(){
Len = input();
work();
calc();
sort(R,R+cnt);
int ccc = 0 ;
int i = 0;
while(i < cnt && ccc < N){
int ttt = R[i].time;
printf("%d ",R[i].time);
while(R[i].time == ttt){
print(R[i].num,R[i].len);
++i;
}
putchar('\n');
++ccc;
}
return 0;
}