题目:给你一些01串,某个前缀的pg为:此前缀长度*拥有此前缀的串的数量。求最大的pg值。
分析:字符串,字典树。
首先,现将字符排序(按长度),短的才可能成为长的前缀。
然后,按照长度的顺序插入到字典树。每个插入的字符进行统计,并记录深度。
最后,枚举所有节点,计算出最大的pg值即可。
说明:注意数组的大小,字典树节点过多会TLE。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
char words[50004][204];
/* Trie define */
#define nodesize 4000004 //节点个数
#define dictsize 2 //字符集大小
typedef struct node1
{
int deep; //深度
int value; //权值
int flag; //值域
node1* next[dictsize];
}tnode;
tnode dict[nodesize];
int ID[256];
class Trie
{
private:
int max;
int size;
tnode* root;
public:
Trie() {makeID(); initial();}
void makeID() {ID['0'] = 0;ID['1'] = 1;}
void initial() {
memset( dict, 0, sizeof( dict ) );
root=NULL; size=0; root=newnode();
}
tnode* newnode() {return &dict[size ++];}
void insert( char* word, int L ) {
tnode* now = root;
for ( int i = 0 ; i < L ; ++ i ) {
if ( !now->next[ID[word[i]]] )
now->next[ID[word[i]]] = newnode();
now = now->next[ID[word[i]]];
now->deep = i+1;
now->value ++;
}now->flag = 1;
}
void output(){
max = 0;
for ( int i = 0 ; i < size ; ++ i )
if ( max < dict[i].value*dict[i].deep )
max = dict[i].value*dict[i].deep;
printf("%d\n",max);
}
}trie;
/* Trie end */
int cmp( const void *a, const void *b )
{
return strlen((char*)a) - strlen((char*)b);
}
int main()
{
int T,n;
while ( scanf("%d",&T) != EOF )
for ( int t = 1 ; t <= T ; ++ t ) {
scanf("%d",&n);
for ( int i = 0 ; i < n ; ++ i )
scanf("%s",words[i]);
qsort( words, n, sizeof(words[0]), cmp );
trie.initial();
for ( int i = 0 ; i < n ; ++ i )
trie.insert( words[i], strlen(words[i]) );
trie.output();
}
return 0;
}