原始题目
1115: 最短的名字
- Time Limit: 5 Sec
- Memory Limit: 64 Mb
- Submitted: 2057
- Solved: 801
Description
在一个奇怪的村子中,很多人的名字都很长,比如 aaaaa, bbb and abababab。
名字这么长,叫全名显然起来很不方便。所以村民之间一般只叫名字的前缀。比如叫'aaaaa'的时候可以只叫'aaa',因为没有第二个人名字的前三个字母是'aaa'。不过你不能叫'a',因为有两个人的名字都以'a'开头。村里的人都很聪明,他们总是用最短的称呼叫人。输入保证村里不会有一个人的名字是另外一个人名字的前缀(作为推论,任意两个人的名字都不会相同)。
如果村里的某个人要叫所有人的名字(包括他自己),他一共会说多少个字母?
输入第一行为数据组数\(T (T≤10)\)。每组数据第一行为一个整数 n\((1≤n≤1000)\) ,即村里的人数。以下\(n\)行每行为一个人的名字(仅有小写字母组成)。输入保证一个村里所有人名字的长度之和不超过 \(10^{6}\)。
Output
对于每组数据,输出所有人名字的字母总数。
1
3
aaaaa
bbb
abababab
Sample Output
5
Hint
Source
湖南省第八届大学生计算机程序设计竞赛
题目大意
如题
解题思路
建立字典树,每个结点的 value 值储存单词字母的出现次数。
- 对于每个单词,统计第一个出现 value 值为 1 的位置(表示到这里后面没有相同单词前缀)
- 求和,完成任务
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| #include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include <set> #include <string> #include <cstring> #include <stack> #define rep(i,a,n) for(int i=a;i<n;++i) #define per(i,a,n) for(int i=n-1;i>=a;--i) using namespace std; const int maxn=1e5+5; const int maxl=26;
typedef long long ll; typedef struct Trie { int v; Trie* next[maxl]; }Trie;
Trie *root; void iniTrie() { root=(Trie*)malloc(sizeof(Trie)); for(int i=0;i<maxl;i++) root->next[i]=NULL; root->v=-1; }
bool creTrie(string a) { int l=a.length(); Trie *p=root,*q; for(int i=0;i<l;i++) { int id=a[i]-'a';
if(p->next[id]==NULL){
q=(Trie*) malloc(sizeof(Trie)); q->v=1; for(int j=0;j<maxl;j++) q->next[j]=NULL; p->next[id]=q; p=p->next[id];
} else{ p=p->next[id]; p->v++; } } return 1; } int cntTrie(string ss) { int l=ss.length(); Trie *p=root,*q; for(int i=0;i<l;i++) { int id=ss[i]-'a'; p=p->next[id]; if(p->v==1) return i+1;
} }
void delTrie(Trie *p) { int i; for(i=0;i<maxl;i++) { if(p->next[i] != NULL) delTrie(p->next[i]); } free(p);
p==NULL; return ; }
string s[maxn]; int t,ccount,n; int main() { ios::sync_with_stdio(false); cin>>t; while(t--){ iniTrie(); cin>>n; rep(i,0,n){ cin>>s[i]; creTrie(s[i]); } int aans=0; rep(i,0,n){ aans+=cntTrie(s[i]); } cout<<aans<<endl; delTrie(root); } }
|
收获与反思
灵活运用字典树的染色和统计功能