UVa 11488 - Hyper Prefix Sets

题目:给你一些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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值