UVa 11148 Hyper Prefix Sets (Trie)

来源:互联网 发布:美国传播学专业知乎 编辑:程序博客网 时间:2024/05/22 14:54

题目链接: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;}



原创粉丝点击