UVALive - 3703 Billing Tables Tire、字典树
2017-03-29 18:48
381 查看
Billing Tables
UVALive- 3703
In the world of telecommunications phone calls to different phone numbers have to be charged using different rate or different billing plan. International Carrier of Phone Communications (ICPC) has an antique billing table that determines which phone call
has to be charged using which billing plan.
Each international phone number has 11 digits. The billing table has n lines. Each line specifies a range of prefixes of phone numbers like “
7919 - 921”. This specification means that all phone numbers starting from 7919, 7920, and
7921 match this line. A billing plan name is specified for each prefix. To determine a billing plan for a call, the table is scanned from top to bottom and the first matching line determines the billing plan. If no match is found, the phone number is invalid
and no billing plan is needed. A special billing plan named “
invalid” (without quotes) is used as an alternative way to define invalid phone numbers. Some billing plans are used for quite differently looking phone numbers and their names may be
specified on different lines in different places of the table.
ICPC’s billing table is old and contains many entries. Some of those entries may not be even used anymore. It is very hard to figure out which phone numbers each billing plan is actually used for. The ICPC’s management has reached a decision to transform
this billing table into a more legible format. In this new format table consists of the lexicographically ordered list of simple prefixes (without the “
-” range feature of the old format) with a billing plan name for each prefix. No prefix of
this new billing table should be a prefix of any other prefix from the table. Thus, a simple dictionary lookup (binary search, for example) will be sufficient to figure out a billing plan for a given phone number. Finding all phone numbers for a given billing
plan will also become quite a simple task. The number of lines in the new billing table should be minimized. Billing plan named “
invalid” should not be present in the new billing table at all, since invalid phone numbers will be denoted by absence
of the corresponding prefix in the new billing table.
Input
The input will contain several test cases, each of them as described below. Consecutive test cases are separated by a single blank line.
The first line of the input file contains a single integer number n (1 ≤ n ≤ 100) — the number of lines in the old billing table. The following n lines describe the old billing table with one rule on a line. Each rule contains four tokens separated
by spaces — prefix A, minus sign (“
-”), prefix B, and billing plan name. Prefixes contain from 1 to 11 digits each, and the billing plan name contains from 1 to 20 lower case letters.
Further, let us denote with |A| the number of digits in the prefix A. It is true that 1 ≤ |B| ≤ |A| ≤ 11. Moreover, last |B| digits of prefix A form a string that is lexicographically equal or precedes B.
Such pair of prefixes A and B matches all phone numbers with the first |A| − |B| digits matching the first digits of A and with the following |B| digits being lexicographically between the last |B|
digits ofA and B (inclusive).
Output
For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.
Write to the output file a single integer number k — the minimal number of lines that the new table should contain to describe the given old billing table. Then write k lines with the lexicographically ordered new billing table. Write two
tokens separated by a space on each line — the prefix and the billing plan name. Note, that the prefix in the new billing table shall contain at least one digit.
If all phone numbers are invalid (every phone number has no matching line or matches line with billing plan “
invalid”) then the output file should contain just number zero.
Sample Input
8 7919 - 921 cell 7921800 - 999 priv 1 - 1 usa 760 - 9 rsv 7928 - 29 rsv 7600 - 7899 spec 73 - 77 invalid 7 - 7 cis
Sample Output
35 1 usa 70 cis 71 cis 72 cis 76 rsv 77 spec 78 spec 790 cis 7910 cis 7911 cis 7912 cis 7913 cis 7914 cis 7915 cis 7916 cis 7917 cis 7918 cis 7919 cell 7920 cell 7921 cell 7922 cis 7923 cis 7924 cis 7925 cis 7926 cis 7927 cis 7928 rsv 7929 rsv 793 cis 794 cis 795 cis 796 cis 797 cis 798 cis 799 cis
Source
UVALive - 3703,UVA
- 1385, POJ - 3149
NEERC 2006
My Solution
题意:对于11位数字串(电话号码),按优先级给定n个区间,每个区间有一个标记。若一个电话号码在某个区间内(如有多个则取优先级最高的区间),则电话号码具有该区间的标记。求一个最小前缀与标记的对应表,使若一个号码的前面与某个前缀匹配,则该号码一定具有该前缀的标记,且不能再与其它前缀匹配。
Tire、字典树
把区间按照从上到下的顺序插入到Tire中,每个根到叶子节点的路径就是一个符合要求的前缀。每个节点都表示一个电话号码
前缀,若某一个节点被一个区间完全覆盖或者几个具有相同标记的区间完全覆盖,则可作为一个叶子节点,否则继续拓展。
每次拓展的时候,把原标记往下推,然后刷新当前节点的标记。
节点个数大于11*2*n,但不会特别大。
复杂度 略大于节点总数sum,O(T*sum)
#include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef long long LL; const int MAXN = 1e2 + 8; const int MAX_SIZE = 12; const int CHAR_SIZE = 10; //Tire int ch[100008][CHAR_SIZE], danger[100008], tot; inline void _insert(char *s1, char *s2, int mark) { int u1 = 0, u2 = 0, i, j, len = strlen(s1); for(i = 0; i < len; i++){ for(j = 0; j < CHAR_SIZE; j++){ if(ch[u1][j] == 0) ch[u1][j] = ++tot; if(ch[u2][j] == 0) ch[u2][j] = ++tot; if(danger[u1] > 0) danger[ch[u1][j]] = danger[u1]; if(danger[u2] > 0) danger[ch[u2][j]] = danger[u2]; } danger[u1] = danger[u2] = 0; if(u1 == u2){ //cout << s1[i] << " " << s2[i] << endl; for(j = s1[i] - '0' + 1; j < s2[i] - '0'; j++){ danger[ch[u1][j]] = mark; } } else{ for(j = s1[i] - '0' + 1; j < CHAR_SIZE; j++){ danger[ch[u1][j]] = mark; } for(j = 0; j < s2[i] - '0'; j++){ danger[ch[u2][j]] = mark; } } u1 = ch[u1][s1[i]-'0']; u2 = ch[u2][s2[i]-'0']; } danger[u1] = danger[u2] = mark; } char str1[MAXN][MAX_SIZE], str2[MAXN][MAX_SIZE], plan[MAXN][2*MAX_SIZE]; int toplan[MAXN], ans; bool valid[MAXN]; void dfs1(int u) { if(danger[u] > 0){ ans += valid[danger[u]]; return; } if(ch[u][0] == 0) return; bool f = true; for(int i = 0; i < CHAR_SIZE; i++){ dfs1(ch[u][i]); if(danger[ch[u][i]] != danger[ch[u][0]]) f = false; } if(f && valid[danger[ch[u][0]]] && u){//! ans -= 9; danger[u] = danger[ch[u][0]]; } } char s[MAX_SIZE]; void dfs2(int u, int len) { if(danger[u] > 0){ if(valid[danger[u]]){ for(int i = 0; i < len; i++){ putchar(s[i]); } putchar(' '); printf("%s\n", plan[danger[u]]); } return; } if(ch[u][0] == 0) return; for(int i = 0; i < CHAR_SIZE; i++){ s[len] = '0' + i; dfs2(ch[u][i], len + 1); } } int main() { #ifdef LOCAL freopen("19.in", "r", stdin); //freopen("19.out", "w", stdout); #endif // LOCAL //ios::sync_with_stdio(false); cin.tie(0); int T, n, i, j, len1, len2; bool f = true; while(scanf("%d", &n) != EOF){ if(!f) putchar('\n'); else f = false; memset(ch, 0, sizeof ch); memset(valid, false, sizeof valid); memset(danger, 0, sizeof danger); ans = tot = 0; for(i = 1; i <= n; i++){ scanf("%s%*s%s%s", str1[i], str2[i], plan[i]); len1 = strlen(str1[i]); len2 = strlen(str2[i]); for(j = len2 - 1; j >= 0; j--) str2[i][len1-len2+j] = str2[i][j]; for(j = 0; j < len1 - len2; j++) str2[i][j] = str1[i][j]; if(strcmp(plan[i], "invalid") != 0) valid[i] = true; toplan[i] = i; for(j = 1; j < i; j++){ if(strcmp(plan[j], plan[i]) == 0){ toplan[i] = j; break; } } } for(i = n; i >= 1; i--){ //printf("%s %s\n", str1[i], str2[i]); _insert(str1[i], str2[i], toplan[i]); } dfs1(0); printf("%d\n", ans); dfs2(0, 0); } return 0; }
Thank you!
------from ProLights
相关文章推荐
- UVALive 3703 (LA 3703) Billing Tables Trie树
- uva 1385 - Billing Tables(字典树)
- UVALive 3942 - Remember the Word(DP,字典树)
- UVALive 4815 || SYSU 2387 Kids' Wishes dfs+(字典树哈希)
- uvalive 5026 字典树典型
- UVA Live 5029 Encoded Barcodes 字典树-水题
- UVALive 7043 International Collegiate Routing Contest(字典树)
- UVAlive 2326 Moving Tables(贪心 + 区间问题)
- UVALive 5913 字典树
- 【Uvalive3942】Remember the Word——字典树+dp
- UVa Live Archive 2326 - Moving Tables
- UVALive 3942 Remember the word 字典树 动态规划
- UVAlive 2326 Moving Tables(贪心 + 区间问题)
- UVALive 2326 Moving Tables 贪心
- UVALive 2326 Moving Tables(贪心+不相交区间问题)
- UVALive 3942 Remember the Word(字典树+dp)
- uvalive 2326 - Moving Tables(区间覆盖问题)
- uvalive 2326 - Moving Tables(区间覆盖问题)
- UVALive 6133 Cellphone Typing(字典树)
- UVALive 7043 International Collegiate Routing Contest 字典树,递归