这道题也是卡了挺久的。

给出一个字符串比较的算法,有n个字符串两两比较一次,问一共会有多少次比较。

因为节点会很多,所以Tire树采用了左儿子右兄弟的表示法来节省空间。

假设两个不相等的字符串的最长公共前缀的长度为i,那么比较次数应该是2i+1。

如果两个字符串相等,比较次数则是2i+2.

可以像大白书上一样先构建好Tire树,然后DFS统计答案。

  1. #include <cstdio>
  2. #include <cstring>
  3.  
  4. const int maxnode = * + ;
  5.  
  6. struct Tire
  7. {
  8. int sz;
  9. int son[maxnode], bro[maxnode], tot[maxnode];
  10. char ch[maxnode];
  11. long long ans;
  12. void clear() { sz = ; son[] = bro[] = tot[] = ; }
  13.  
  14. void insert(char* s)
  15. {
  16. int u = , v, n = strlen(s);
  17. tot[]++;
  18. for(int i = ; i <= n; i++)
  19. {
  20. bool found = false;
  21. for(v = son[u]; v; v = bro[v])
  22. if(ch[v] == s[i]) { found = true; break; }
  23. if(!found)
  24. {
  25. v = sz++;
  26. son[v] = ;
  27. bro[v] = son[u];
  28. son[u] = v;
  29. tot[v] = ;
  30. ch[v] = s[i];
  31. }
  32. u = v;
  33. tot[u]++;
  34. }
  35. }
  36.  
  37. void dfs(int d, int u)
  38. {
  39. if(son[u] == ) { ans += tot[u] * (tot[u]-) * d; return; }//叶节点
  40. long long sum = ;
  41. for(int v = son[u]; v; v = bro[v])
  42. sum += tot[v] * (tot[u] - tot[v]);
  43. ans += sum / * (d * + );
  44. for(int v = son[u]; v; v = bro[v]) dfs(d+, v);
  45. }
  46.  
  47. long long count()
  48. {
  49. ans = ;
  50. dfs(, );
  51. return ans;
  52. }
  53. }tire;
  54.  
  55. const int maxl = + ;
  56. char s[maxl];
  57.  
  58. int main()
  59. {
  60. //freopen("in.txt", "r", stdin);
  61.  
  62. int n, kase = ;
  63. while(scanf("%d", &n) == && n)
  64. {
  65. tire.clear();
  66. for(int i = ; i < n; i++) { scanf("%s", s); tire.insert(s); }
  67. printf("Case %d: %lld\n", ++kase, tire.count());
  68. }
  69.  
  70. return ;
  71. }

代码君

也可以边插入字符串边统计,代码更短,而且速度也更快。这种做法是从某位菊苣的博客中看到的。

  1. #include <cstdio>
  2. #include <cstring>
  3.  
  4. const int maxnode = * + ;
  5.  
  6. long long ans;
  7.  
  8. struct Tire
  9. {
  10. int son[maxnode], bro[maxnode], tot[maxnode];
  11. char ch[maxnode];
  12. int sz;
  13. void clear() { sz = ; son[] = bro[] = tot[] = ; }
  14.  
  15. void insert(char* s)
  16. {
  17. int u = , v, n = strlen(s);
  18. tot[]++;
  19. for(int i = ; i <= n; i++)
  20. {
  21. bool found = false;
  22. for(v = son[u]; v; v = bro[v])
  23. if(ch[v] == s[i]) { found = true; break; }
  24. if(!found)
  25. {
  26. v = sz++;
  27. son[v] = ;
  28. bro[v] = son[u];
  29. son[u] = v;
  30. tot[v] = ;
  31. ch[v] = s[i];
  32. }
  33. ans += (tot[u] - - tot[v]) * ( * i + );
  34. if(i == n) ans += tot[v] * ( * i + );
  35. u = v;
  36. tot[u]++;
  37. }
  38. }
  39. }tire;
  40.  
  41. const int maxl = + ;
  42. char s[maxl];
  43.  
  44. int main()
  45. {
  46. //freopen("in.txt", "r", stdin);
  47.  
  48. int n, kase = ;
  49. while(scanf("%d", &n) == && n)
  50. {
  51. tire.clear();
  52. ans = ;
  53. for(int i = ; i < n; i++) { scanf("%s", s); tire.insert(s); }
  54. printf("Case %d: %lld\n", ++kase, ans);
  55. }
  56.  
  57. return ;
  58. }

代码君

UVa 11732 (Tire树) "strcmp()" Anyone?的更多相关文章

  1. UVa 1401 (Tire树) Remember the Word

    d(i)表示从i开始的后缀即S[i, L-1]的分解方法数,字符串为S[0, L-1] 则有d(i) = sum{ d(i+len(x)) | 单词x是S[i, L-1]的前缀 } 递推边界为d(L) ...

  2. uva 11732 (trie树)

    题意:求N个字符串两两比较,共比较了多少次? #include<iostream> #include<cstring> #include<cstdio> using ...

  3. UVA 11732 - strcmp() Anyone?(Trie)

    UVA 11732 - strcmp() Anyone? 题目链接 题意:给定一些字符串,要求两两比較,须要比較的总次数(注意.假设一个字符同样.实际上要还要和'\0'比一次,相当比2次) 思路:建T ...

  4. 左儿子右兄弟Trie UVA 11732 strcmp() Anyone?

    题目地址: option=com_onlinejudge&Itemid=8&category=117&page=show_problem&problem=2832&qu ...

  5. Codeforces 714C. Sonya and Queries Tire树

    C. Sonya and Queries time limit per test:1 second memory limit per test: 256 megabytes input:standar ...

  6. 中文分词系列(二) 基于双数组Tire树的AC自动机

    秉着能偷懒就偷懒的精神,关于AC自动机本来不想看的,但是HanLp的源码中用户自定义词典的识别是用的AC自动机实现的.唉-没办法,还是看看吧 AC自动机理论 Aho Corasick自动机,简称AC自 ...

  7. 中文分词系列(一) 双数组Tire树(DART)详解

    1 双数组Tire树简介 双数组Tire树是Tire树的升级版,Tire取自英文Retrieval中的一部分,即检索树,又称作字典树或者键树.下面简单介绍一下Tire树. 1.1 Tire树 Trie ...

  8. [数据结构]字典树(Tire树)

    概述: Trie是个简单但实用的数据结构,是一种树形结构,是一种哈希树的变种,相邻节点间的边代表一个字符,这样树的每条分支代表一则子串,而树的叶节点则代表完整的字符串.和普通树不同的地方是,相同的字符 ...

  9. Tire树

    Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种. 典型应用是用于统计和排序大量的字符串(但不仅限于字符串), 所以经常被搜索引擎系统用于文本词频统计. 字典树(Trie)可以保存 ...

随机推荐

  1. sqlserver 获取时间年月日时分秒

    转自:http://blog.itpub.net/14766526/viewspace-1156100/ select GETDATE() as '当前日期',DateName(year,GetDat ...

  2. JSP访问Spring中的bean

    JSP访问Spring中的bean <%@page import="com.sai.comment.po.TSdComment"%> <%@page import ...

  3. JS中的className含义

    问题描述:     JS中的className含义 问题解决:     className说明:         className属性可以设置和返回元素的class属性 可以有两种方法来获取对象的c ...

  4. WCF 基础

    ServiceModel 配置元素 Binding 配置元素: 客户端Web.config: <?xml version="1.0" encoding="utf-8 ...

  5. ios开发之多线程资源争夺

    上一篇介绍了常用的多线程技术,目前开发中比较常用的是GCD,其它的熟悉即可.多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用率来提高系统的整体性能,但是会出现多个线程对同一资源 ...

  6. hdu 2196

    树形dp 本文出自   http://blog.csdn.net/shuangde800 题目传送门 题意: 给出一棵树,求离每个节点最远的点的距离 思路: 把无根树转化成有根树分析, 对于上面那棵树 ...

  7. iOS 委托和协议区别和联系

    iOS上的协议类似于C#.Java上面的接口,他是从类中抽出来的一系列方法,但方法的实现是在实现这个协议的类中,任何实现这个协议的类都需要实现协议类中的@require方法: 委托是一种设计模式,是一 ...

  8. unit3d 4.6 document open solution

    发现4.6 的 本地 文档字体解析采用 fonts.googleapis.com ,可是google 自古就与天朝不在一个鼻孔,所以你打开往往需要半天. 网上查了一下,把所有本地的*.html 文档  ...

  9. IOS版UC我的视频地址

    UC浏览器/Library/Application Support/offlineVideos

  10. StringBuffer用法

    public class StringBufferTest { public static void main(String[] args) { StringBuffer sb=new StringB ...