字典树

2017-08-03  本文已影响0人  kisslight

UVA 11488
题目链接https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2483

给定若干个01字符串,从这些字符串中选出一个集合,使得这个集合所有字符串的最长公共前缀和字符串个数相乘最大.

思路:
比较裸的一棵字典树,回想一下字典树的性质,因为是在不同的节点的时候进行分叉,而一个节点可能又多个分叉点,如果有3个分叉点说明到这个节点的长度就是这三个分叉也就是三个字符串的最长公共前缀的长度,然后再乘分叉数和原来的ans比较就可以获得答案了

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
const int maxnode = 50010 * 2;
const int sigma_size = 12;
long long ans;

struct Trie{
    int ch[maxnode][sigma_size];
    int cnt[maxnode];
    int sz;
    void clear(){
        sz = 1;
        ans = 0;
        memset(ch, 0, sizeof(ch));
        memset(cnt, 0, sizeof(cnt));
    }
    int idx(char c){
        return c - '0';
    }
    void insert(char *s){
        int u = 0, n = strlen(s);
        for(int i = 0;i < n;i ++){
            int c = idx(s[i]);
            if (!ch[u][c]){
                memset(ch[sz], 0, sizeof(ch[sz]));
                ch[u][c] = sz ++;
            }
            u = ch[u][c];
            cnt[u] ++;
            ans = max(ans,(long long)cnt[u] * (i + 1));
        }
    }
};

Trie trie;
int n, t;
char ss[maxnode];
int main(){
    scanf("%d", &t);
    while (t --){
        trie.clear();
        scanf("%d", &n);
        for (int i = 0;i < n;i ++){
            scanf("%s", ss);
            trie.insert(ss);
        }
        cout << ans << endl;
    }
    return 0;
}

上一篇下一篇

猜你喜欢

热点阅读