Dictionary Size

uvaLive5913:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3924

题意:给你n个串,然后你可以用串的非空前缀和非空后缀组成新的单词,问形成新的加上原来的一共有多少种不同的串。

题解:很容易想到,先计算出前缀有多少种,后缀有多少种,然后prenum*sufnum即可,但是这样会有重复计算,必须把重复的减去。所以要思考什么情况下会有重复。

例如 ax 和xb来说,a和xb和ax和b,就是重复。所以要统计多少以x结尾的前缀num1和多少以x开头的后缀,然后ans-=num1*num2即可,但是题目要求的是一共多少个串,所以要考虑原来的,对于原来的串来说,只要len>=2,都可以由前缀和后缀组合而来,所以对于这样的串不需要考虑,结果集中已经包含,只要把len==1的数目加上去即可,因为这些串是无法经过组合形成的。

 1 #include<cstring>
 2 #include<vector>
 3 #include<cstdio>
 4 using namespace std;
 5 const int maxnode = 4000*1000 + 10;
 6 const int sigma_size = 26;
 7 char word[102];
 8 int n,m;
 9 long long pre[30],suf[30];
10 bool C[30];
11 struct Trie {
12   int head[maxnode]; // head[i]为第i个结点的左儿子编号
13   int next[maxnode]; // next[i]为第i个结点的右兄弟编号
14   char ch[maxnode];  // ch[i]为第i个结点上的字符
15   int sz; // 结点总数
16   void clear() {
17     sz = 1;
18     head[0] = next[0] = 0;
19     }
20   void insert(const char *s,int to) {
21     int u = 0, v;
22     for(int i = 0; i <to; i++) {
23       bool found = false;
24       for(v = head[u]; v != 0; v = next[v])
25         if(ch[v] == s[i]) { // 找到了
26           found = true;
27           break;
28         }
29       if(!found) {
30         v = sz++; // 新建结点5
31         ch[v] = s[i];
32         if(i!=0)
33         pre[s[i]-‘a‘+1]++;
34         next[v] = head[u];
35         head[u] = v; // 插入到链表的首部
36         head[v] = 0;
37       }
38       u = v;
39     }
40 }
41 void insert2(const char *s,int to) {
42     int u = 0, v;
43     for(int i = to-1; i>=0; i--) {
44       bool found = false;
45       for(v = head[u]; v != 0; v = next[v])
46         if(ch[v] == s[i]) { // 找到了
47           found = true;
48           break;
49         }
50       if(!found) {
51         v = sz++; // 新建结点
52         ch[v] = s[i];
53         if(i!=to-1)
54         suf[s[i]-‘a‘+1]++;
55         next[v] = head[u];
56         head[u] = v; // 插入到链表的首部
57         head[v] = 0;
58       }
59       u = v;
60     }
61 }
62 }trie1,trie2;
63 int main() {
64   while(~scanf("%d",&n)) {
65        trie1.clear();
66        trie2.clear();
67        memset(pre,0,sizeof(pre));
68        memset(suf,0,sizeof(suf));
69        memset(C,0,sizeof(C));
70       for(int i=1;i<=n;i++){
71         scanf("%s", word);
72          m=strlen(word);
73         trie1.insert(word,m);
74         if(m==1)
75             C[word[0]-‘a‘+1] = 1;
76         trie2.insert2(word,m);
77       }
78       long long ans=0;
79       ans=(long long)(trie1.sz-1)*(trie2.sz-1);
80       for(int i=1;i<=26;i++){
81             if(C[i]==1)ans++;
82          if(suf[i]==0||pre[i]==0)continue;
83         ans-=(suf[i]*pre[i]);
84       }
85       printf("%lld\n",ans);
86   }
87   return 0;
88 }

Dictionary Size

时间: 2024-10-09 19:49:27

Dictionary Size的相关文章

uva 1519 - Dictionary Size(字典树)

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

UVA 1519 - Dictionary Size(Trie树)

UVA 1519 - Dictionary Size 题目链接 题意:有一个字典,里面包含一些词,要求组合新词,新词必须来自原字典,或者由原字典的字符串的非空前缀和非空后缀组成,问一共能组成多少个新词 思路:建Trie树,可以求出不同的前缀和后缀个数,然后相乘,这样做会有一部分重复的 比如Aaaa,aaaA的情况,就重复了,去重的方法可以推理出来 假设前缀A后面有x个a,后缀y个a后面一个A,那么这x和y个一共一边各有(x+1)和(y+1)种情况,相乘一共是(x+1)(y+1)种,那么实际上一共

UVa 1519 Dictionary Size

方法:Trie 看了题解,有两种做法,大致是相通的.这道题重点在于如何判重. 建立两个trie,取名prefix 和 suffix.把所有string插入第一个trie,每个节点就代表一种prefix.同理,把所有string反转之后插入第二个trie,每个节点就代表一个suffix.如果没有重复的话,那么结果就是prefix.size * suffix.size.如何判重呢?如果一个长度至少为2的前缀p以字符c结尾,并且有一个长度至少为2的后缀 s以c开始,那么 p+s.substring(1

BZOJ3806: Neerc2011 Dictionary Size

题解: 这题搞得我真是酸(dan)爽(teng) 原来一直不会,一定会用到什么神奇的东西.因为重复的不知道如何计算. 今天中午睡起来忽然想到好像可以在正trie上故意走无出边,因为这样就保证了这次统计的所有字符串在它的孩子都不会再次被统计到. 然后感觉这题就解了. 然后和别人的程序对拍发现居然一直少计算了什么!去多了? 然后发现没有算上trie上的节点,前面只考虑了在trie后面加字符串... 然后发现好像正反都得特判,然后发现又有重复的!!!这怎么搞!!! 感觉AC无望便去颓了两集火影...

Python dictionary implementation

Python dictionary implementation http://www.laurentluce.com/posts/python-dictionary-implementation/ August 29, 2011 This post describes how dictionaries are implemented in the Python language. Dictionaries are indexed by keys and they can be seen as

JavaScript Dictionary

function Dictionary() { var items = {}; this.has = function(key) { return key in items } this.set = function(key, value) { items[key] = value } this.remove = function(key) { if (this.has(key)) { delete items[key]; return true } return false } this.ge

你真的了解字典(Dictionary)吗?

从一道亲身经历的面试题说起 半年前,我参加我现在所在公司的面试,面试官给了一道题,说有一个Y形的链表,知道起始节点,找出交叉节点. 为了便于描述,我把上面的那条线路称为线路1,下面的称为线路2. 思路1 先判断线路1的第一个节点的下级节点是否是线路2的第一个节点,如果不是,再判断是不是线路2的第二个,如果也不是,判断是不是第三个节点,一直到最后一个. 如果第一轮没找到,再按以上思路处理线路一的第二个节点,第三个,第四个... 找到为止. 时间复杂度n2,相信如果我用的是这种方法,可肯定被Pass

javascript字典数据结构常用功能实现

必知必会啊. function Dictionary(){ var items = {}; this.has = function (key) { return key in items; }; this.set = function(key, value){ items[key] = value; }; this.remove = function(key){ if (this.has(key)){ delete items[key]; return true; } return false;

Python自动化开发从浅入深-语言基础(collection)

-- collection是对内置数据类型的一种扩充,其主要扩充类型包括: 1.namedtuple(): 生成可以使用名字来访问元素内容的tuple子类,以增强可读性. def namedtuple(typename, field_names, verbose=False, rename=False): """Returns a new subclass of tuple with named fields. 返回一个新的命名域元组子类,typename为类型名,field