uva 1385 - Billing Tables(字典树)

题目链接:uva 1385 - Billing Tables

题目大意:给定n个电话前缀,每个前缀是一个区域的前缀,现在要生成一个新的电话单,即对于每个电话号码,从旧的电话单上从前向后遍历,如果出现前缀匹配,则该电话号码对应的即为当前的区号,要求生成的新电话单尽量小。

解题思路:用dfs建立字典树,在区间范围内的点对应均为对应的区号,注意如果70、71、72、...79都为SB的话,那么可以合并成7,并且对应区号为SB。

注意合并的条件为区号相同即可,并不是说对应旧电话单匹配位置相同。

注意这组数据:0 - 9 all

#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <map>
#include <iostream>
#include <algorithm>

using namespace std;
const int sigma_size = 10;
typedef pair<string, string> pii;

struct Node {
    int val;
    Node* next[sigma_size];

    Node() {
        val = 0;
        memset(next, 0, sizeof(next));
    }
};

void clear(Node* &p);
void insert (Node* &p, int d, int L, int R, int tig);
void dfs(Node* p, string str);
int pushup(Node* &p, int tig);

map<string, int> g;

int n, m;
string l, r, name[105];
Node* root = NULL;

vector<pii> vec;

void init () {
    vec.clear();
    g.clear();
    string tmp;

    for (int i = 1; i <= m; i++) {
        cin >> l >> tmp >> r >> name[i];

        tmp = "";
        int d = l.length() - r.length();

        for (int i = 0; i < d; i++)
            tmp += l[i];
        tmp += r;
        r = tmp;

        if (l > r)
            continue;

        int k = i;
        if (g.count(name[i]))
            k = g[name[i]];
        else
            g[name[i]] = i;

        insert(root, 0, 1, 1, k);
    }
}

int main () {
    int cas = 0;
    while (cin >> m) {
        if (cas++)
            cout << endl;

        init();
        pushup(root, m+1);
        dfs(root, "");
        clear(root);

        printf("%lu\n", vec.size());
        for (int i = 0; i < vec.size(); i++)
            cout << vec[i].first << " " << vec[i].second << endl;
    }
    return 0;
}

int pushup (Node* &p, int tig) {
    if (p == NULL) {
        p = new Node;
        return p->val = tig;
    }

    if (p->val)
        tig = p->val;

    int k = pushup(p->next[0], tig);
    for (int i = 1; i < sigma_size; i++) {
        if (k != pushup(p->next[i], tig))
            k = 0;
    }

    return p->val = k;
}

void dfs (Node* p, string str) {
    if (p != root && p->val) {
        if (p->val <= m && name[p->val] !=  "invalid")
            vec.push_back(make_pair(str, name[p->val]));
        return ;
    }

    for (int i = 0; i < sigma_size; i++) {
        if (p->next[i] != NULL) {
            char ch = ‘0‘ + i;
            dfs(p->next[i], str + ch);
        }
    }
}

void insert (Node* &p, int d, int L, int R, int tig) {
    if (p == NULL)
        p = new Node;

    if (p->val)
        tig = p->val;

    if (d >= l.length()) {
        p->val = tig;
        return;
    }

    if (L == 0 && R == 0) {
        p->val = tig;
        return;
    } else if (L == 0) {
        insert(p->next[r[d]-‘0‘], d + 1, 0, 1, tig);
        for (int i = 0; ‘0‘ + i < r[d]; i++)
            insert(p->next[i], d + 1, 0, 0, tig);
    } else if (R == 0) {
        insert(p->next[l[d]-‘0‘], d + 1, 1, 0, tig);
        for (int i = l[d] - ‘0‘ + 1; i < sigma_size; i++)
            insert(p->next[i], d + 1, 0, 0, tig);
    } else if (r[d] == l[d]) {
        insert(p->next[l[d]-‘0‘], d + 1, 1, 1, tig);
    } else {
        insert(p->next[l[d]-‘0‘], d + 1, 1, 0, tig);
        insert(p->next[r[d]-‘0‘], d + 1, 0, 1, tig);
        for (int i = l[d] + 1; i < r[d]; i++)
            insert(p->next[i-‘0‘], d + 1, 0, 0, tig);
    }
}

void clear(Node* &p) {
    for (int i = 0; i < sigma_size; i++) {
        if (p->next[i] != NULL)
            clear(p->next[i]);
    }
    delete p;
    p = NULL;
}
时间: 2024-10-14 12:04:18

uva 1385 - Billing Tables(字典树)的相关文章

uva 1556 - Disk Tree(字典树)

题目连接:uva 1556 - Disk Tree 题目大意:给出N个目录关系,然后按照字典序输出整个文件目录. 解题思路:以每个目录名作为字符建立一个字典树即可,每个节点的关系可以用map优化. #include <cstdio> #include <cstring> #include <map> #include <string> #include <iostream> #include <algorithm> using nam

uva 11732 - strcmp() Anyone?(字典树)

题目链接:uva 11732 - strcmp() Anyone? 题目大意:给定n个串,然后两两之间比较,问说总共要比较多少次. 解题思路:字典树,建立出字典树,然后根据字典树的性质在节点记录有多少个字符串包含该节点.因为节点的个数比较多,所以用左孩子右兄弟的方法建立字典树. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long

UVA Phone List (字典树)(查询是否有前缀或自身是其他的前缀)

Phone List Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16341   Accepted: 5228 Description Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogu

uva 1519 - Dictionary Size(字典树)

题目链接:uva 1519 - Dictionary Size 题目大意:给出n个字符串组成的字典,现在要添加新的单词,从已有单词中选出非空前缀和非空后缀,组成新单词.问说能组成多少个单词. 解题思路:建立一棵前缀树和一棵后缀树,有多少节点即为有多少个前缀,扣除中间的部分即可加上长度为1的字符串即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const

UVA 12333 大数,字典树

题意:给一个数字,看他最小是第几个菲波那切数列的前缀. 分析: 大数模板就是吊哦. 将菲波那切数列前500个数字放到字典树上.注意插入的时候不能像普通一样,只在尾节点处标记,而是一路标记下去. #include <bits/stdc++.h> using namespace std; const int NV = 10000; const int ra = 10; int ten[4] = {1,ra,ra*ra,ra*ra*ra}; int radix = ra*ra*ra*ra; stru

UVA 11732 strcmp() Anyone? (压缩版字典树)

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2832 按照正常的字典树建树会MLE 所以需要采用树的压缩算法来建树 #include <cstdio> #include <iostream> #include <cstring> #define maxn 4000010 #define ma

uva 1462 - Fuzzy Google Suggest(字典树+dfs)

题目链接:uva 1462 - Fuzzy Google Suggest 题目大意:模拟google的模糊搜索,给定给一个字符串集合,然后有n次搜索,每次有一个整数x和一个字符串,表示可以对字符串进行x次修改,包括增加.修改和删除一个字符,问修改后的字符可能是字符集中有多少个字符串的前缀. 解题思路:先建立字典树,对于每次搜索,在字典树上进行dfs,根据参数x和字符串匹配的位置进行处理,对于匹配到末尾的位置标记为2,然后对于第二次dfs,搜索每个分支上最早出现2的位置即可. #include <

uva 11488 - Hyper Prefix Sets(字典树)

H Hyper Prefix Sets Prefix goodness of a set string is length of longest common prefix*number of strings in the set. For example the prefix goodness of the set {000,001,0011} is 6.You are given a set of binary strings. Find the maximum prefix goodnes

UVA - 11488 字典树

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2483 题意:给定一堆由0,1组成的串,现在要求一个最大值,值的结果为:串前缀*用于此前缀的字符串个数 思路:字典树,在插入字符串的时候就开始统计,对于插入的每个字符串的前缀的值都累加,然后一边插入一边维护最大值即可. #define _CRT_SECURE_NO_DEPRECAT