UVa 11148 Hyper Prefix Sets (Trie)

题目链接:https://vjudge.net/problem/UVA-11488

题意:给定n个字符串,从n个字符串中选出若干个组成字符串集合S。定义P(S)为集合S中所有串的最长公共前缀长度与S中字符串个数的乘积。求一个集合S,使得P(S)最大。

思路:首先将所有串建成一颗Trie树,然后遍历整个Trie树。当遍历到某个结点u时,从起始根节点往下到u构成了一个前缀,以这个为前缀的字符串个数即为u及其子树中单词结点的个数,这两个的乘积便是一个答案。边遍历边统计答案即可。


#include<cstdio>
#include<cstring>
#include<string>
#include<cctype>
#include<iostream>
#include<set>
#include<map>
#include<cmath>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<algorithm>
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int inf = 1e9 + 10;
const int maxnode = 1e7 + 10;
const int sigma_size = 2;
const int maxn = 35;
LL res;
struct Tree
{
	int ch[maxnode][sigma_size];
	int val[maxnode];
	int depth[maxnode], size[maxnode];
    int sz;
    int idx(char c) { return c - '0'; }
    void init() { memset(ch[0], 0, sizeof ch[0]); sz = 1; }
    
    void insert(char *s)
    {
    	int n = strlen(s), u = 0;
    	for(int i = 0; i < n; i++)
    	{
             int c = idx(s[i]);
             if(!ch[u][c])
             {
             	memset(ch[sz], 0, sizeof ch[sz]);
                val[sz] = 0;
                ch[u][c] = sz++;
             }
             u = ch[u][c];
             depth[u] = i+1;
    	}
    	val[u]++;
    }

    int Find(int u)
    {
    	int ans = 0;
    	for(int i = 0; i < 2; i++)
    	{
    		int c = ch[u][i];
    		if(c) ans += Find(c);
    	}
    	if(val[u]) ans += val[u];
    	res = max(res, (LL)depth[u] * ans);
    	return size[u] = ans;
    }

}tree;

int main()
{
	int T, n;
	char s[205];
	scanf("%d", &T);
	while(T--)
	{
		tree.init();
		scanf("%d", &n);
		for(int i = 1; i <= n; i++)
		{
			scanf("%s", s);
			tree.insert(s);
		}
		res = 0;
		tree.Find(0);
        cout << res << endl;
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值