USACO Training Section 3.1 Contact
英語の原題
中国語の翻訳
長い01列の中で長さA,Bの間のサブ列の繰り返し回数を探して、順番に最大のN個の繰り返し回数を出力して、しかも相応のサブ列を出力して、同じサブ列が2進数の大きさで並べて出力することを要求します(行ごとに6個).
データ制限:1<=A<=B<=12、1<=N<50、文字列最大長200000
例:
2 4 2
01010010010001000111101100001010011001111000010010011110010000000
出力:
23
00
15
01 10
表示,00が23回で最も多く,次いで01,10が15回ずつ出現した.
明らかにtriesで行うのが最も適切で、長さは最大12で、triesの各ノードは2つのサブノードを含んで、1つの完全な木を構成して、ノード数は2^13-1です.
構想は順調で、書くのも順調ですが、何度も提出して、フォーマットの上でN回の間違いを犯しました.sigh.その後、スレッドのコードを見て、それはtriesで作ったのではなく、ビット操作で、うん、01の特徴を十分に利用して、とても速くて、プログラミングの上でtriesよりも簡単で、特にカウントの時に遍歴する必要はなくて、出力の時ももっと簡単です.確かにtriesを使うより上手です.何が一番適当なのかを改めて示した.教えてもらいました.
中国語の翻訳
長い01列の中で長さA,Bの間のサブ列の繰り返し回数を探して、順番に最大のN個の繰り返し回数を出力して、しかも相応のサブ列を出力して、同じサブ列が2進数の大きさで並べて出力することを要求します(行ごとに6個).
データ制限:1<=A<=B<=12、1<=N<50、文字列最大長200000
例:
2 4 2
01010010010001000111101100001010011001111000010010011110010000000
出力:
23
00
15
01 10
表示,00が23回で最も多く,次いで01,10が15回ずつ出現した.
明らかにtriesで行うのが最も適切で、長さは最大12で、triesの各ノードは2つのサブノードを含んで、1つの完全な木を構成して、ノード数は2^13-1です.
構想は順調で、書くのも順調ですが、何度も提出して、フォーマットの上でN回の間違いを犯しました.sigh.その後、スレッドのコードを見て、それはtriesで作ったのではなく、ビット操作で、うん、01の特徴を十分に利用して、とても速くて、プログラミングの上でtriesよりも簡単で、特にカウントの時に遍歴する必要はなくて、出力の時ももっと簡単です.確かにtriesを使うより上手です.何が一番適当なのかを改めて示した.教えてもらいました.
/*
ID: blackco3
TASK: contact
LANG: C++
*/
#include <iostream>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
#define _max_pattern_ 13
#define _max_seq_len_ 200001
char sequence[_max_seq_len_] ;
int seq_size, low, up, n_th ;
struct t_tries {
int count ;
t_tries *next[2] ;
} tries_buf[(1<<_max_pattern_)+1] ;
void build_tries( int height ){
for( int pos=1; pos<(1<<(height+1)); pos++ ){
tries_buf[pos].count=0;
if( (pos<<1)>=(1<<(height+1)) )
tries_buf[pos].next[0] = tries_buf[pos].next[1] = 0 ;
else
tries_buf[pos].next[0] = tries_buf+(pos<<1), tries_buf[pos].next[1] = tries_buf+(pos<<1)+1 ;
}
}
struct t_pattern {
int times, len ;
char str[_max_pattern_+1];
} patterns[(1<<_max_pattern_)+1], *p_patterns[(1<<_max_pattern_)+1];
typedef t_pattern *tp_pattern ;
int p_pattern_comp( const void * pt1, const void * pt2){
tp_pattern p1=*(tp_pattern*)pt1, p2=*(tp_pattern*)pt2;
if( p1->times != p2->times )
return p1->times - p2->times ;
if( p1->len != p2->len )
return p2->len - p1->len ;
return -strcmp(p1->str, p2->str);
}
int n_pattern=0;
char cur_pattern[_max_pattern_+1];
void get_count( t_tries *pc, int height) {
if( height>up )
return ;
if( height>=low && pc->count ){
patterns[n_pattern].times = pc->count, patterns[n_pattern].len = height;
memcpy( patterns[n_pattern].str, cur_pattern, height );
patterns[n_pattern++].str[height] = '\0' ;
}
cur_pattern[height]='0';
get_count( pc->next[0], height+1 );
cur_pattern[height]='1';
get_count( pc->next[1], height+1 );
}
int main() {
freopen("contact.in", "r", stdin);
freopen("contact.out", "w", stdout);
cin >> low >> up >> n_th ;
char *p_seq=sequence ;
while ( cin >> p_seq )
p_seq += strlen( p_seq );
seq_size = p_seq-sequence ;
for( p_seq=sequence; *p_seq!='\0'; p_seq++ )
*p_seq -= '0' ;
*p_seq = -1 ;
build_tries(up) ;
char *p_end=p_seq+seq_size-low ;
for( p_seq=sequence; p_seq<p_end && *p_seq!=-1; p_seq++ ) {
register t_tries *p_trie=tries_buf+1 ;
for( register char *pc=p_seq; pc<p_seq+up && *pc!=-1; pc++ )
p_trie=p_trie->next[*pc], p_trie->count++ ;
}
get_count(tries_buf+1,0);
for( int i=0; i<n_pattern; i++){
p_patterns[i] = patterns+i ;
}
qsort( p_patterns, n_pattern, sizeof(tp_pattern), p_pattern_comp );
for( int i=n_pattern-1, pre_times=0, pc=0, tc=0; i>=0; i-- ){
if( pre_times != p_patterns[i]->times ) {
if( pc && tc )
cout << endl ;
if( pc==n_th )
break ;
cout << p_patterns[i]->times << endl ;
pre_times=p_patterns[i]->times, pc++, tc=0 ;
}
if( tc )
cout << " " ;
cout << p_patterns[i]->str , tc++;
if( tc==6 || !i )
cout << endl , tc=0 ;
}
return 0;
}