UVA5913 Dictionary Sizes(字典树)(转载)
题目大意:给出n个旧单词,要从这n个旧单词中构造新单词。构造条件是 S = Sa + Sb,其中Sa为某个旧单词的非空前缀,Sb为某个单词的非空后缀。求所有的新单词和旧单词中有多少个不同的单词。
思路:将所有单词建成一棵字典树,再将所有单词反转并建成一棵字典树。则第一棵树的结点个数即为不同前缀的数量,第二棵树的结点个数为不同后缀的数量。如果不算重复,取两者的乘积即为新单词的数量。
接下来考虑重复的情况。什么样子会重复呢?假设第一棵树中某个前缀为a1a2a3...X,第二棵树中某个后缀为Xb1b2b3...。那么这就一定会有重复,也就是前缀的末字符和后缀的首字符相同时会重复。考虑a1a2a3...Xb1b2b3...,这个X可能出现在前缀里,也可能出现在后缀里,这也就是多算了一种情况。考虑一般情况,假设第一棵树中某个前缀为a1a2a3...XXX..X(一共m个X),第二棵树中某个后缀为XXX...Xb1b2b3...(一共n个X),那么这两个串组成的串a1a2a3XX...Xb1b2b3...中X的数目有m+n+1种可能(0~m+n),而前缀中X的数目有(m+1)种可能(0~m个),同理后缀中X的数目(n+1)种可能,因此我们在实际计算中一共多算了(m+1)*(n+1) - (m+n+1) = m*n次,即前缀中X的数目与后缀中X数目的乘积。
那么,我们只要分别求出两棵树中每个字符的出现次数并减去它们的乘积即可(这是用了加法乘法原理,假设第一棵树中末尾为X的前缀共有3个,分别含a1、a2、a3个X;第二棵树中开头为X的后缀为3个,分别含b1、b2、b3个X,则一共重复算了a1*b1+a1*b2+a1*b3+a2*b1+a2*b2+a2*b3+a3*b1+a3*b2+a3*b3=(a1+a2+a3)*(b1+b2+b3)次)。这里要注意,只统计深度大于1的结点,因为我们要保证前后缀均非空(如前缀X与后缀Xb就不会有重复,因为第一个的X必须要选)。最后,再加上长度为1的旧单词即可,因为我们构造单词时不会造出长度为1的单词。
#include<cstdio>
#include<cstring>
#include<string>
#include<cctype>
#include<iostream>
#include<set>
#include<map>
#include<cmath>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<algorithm>
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int inf = 1e9 + ;
const int maxnode = 4e5 + ;
const int sigma_size = ;
const int maxn = + ;
char s[];
int vis[sigma_size]; struct Tree
{
int ch[maxnode][sigma_size];
int val[maxnode];
int cnt[sigma_size];
int sz;
int idx(char c) { return c - 'a'; }
void init() { memset(ch[], , sizeof ch[]); sz = ; memset(cnt, , sizeof cnt); } void insert(char *s)
{
int n = strlen(s), u = ;
for(int i = ; i < n; i++)
{
int c = idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz], , sizeof ch[sz]);
val[sz] = ;
ch[u][c] = sz++;
if(i) cnt[c]++;
}
u = ch[u][c]; }
val[u] = ;
} }Pre, Suf; int main()
{ int n;
while(scanf("%d", &n) == )
{
Pre.init(); Suf.init();
memset(vis, , sizeof vis);
for(int i = ; i <= n; i++)
{
scanf("%s", s);
Pre.insert(s);
int len = strlen(s);
reverse(s, s+len);
Suf.insert(s);
if(len == ) vis[s[]-'a'] = ;
}
LL ans = LL(Pre.sz-)*LL(Suf.sz-);
for(int i = ; i < sigma_size; i++)
ans -= (LL)Pre.cnt[i] * LL(Suf.cnt[i]);
for(int i = ; i < sigma_size; i++)
if(vis[i]) ++ans;
cout << ans << endl;
}
return ;
}
UVA5913 Dictionary Sizes(字典树)(转载)的更多相关文章
- uva 1519 - Dictionary Size(字典树)
题目链接:uva 1519 - Dictionary Size 题目大意:给出n个字符串组成的字典.如今要加入新的单词,从已有单词中选出非空前缀和非空后缀,组成新单词. 问说能组成多少个单词. 解题思 ...
- [转载]字典树(trie树)、后缀树
(1)字典树(Trie树) Trie是个简单但实用的数据结构,通常用于实现字典查询.我们做即时响应用户输入的AJAX搜索框时,就是Trie开始.本质上,Trie是一颗存储多个字符串的树.相邻节点间的边 ...
- 萌新笔记——用KMP算法与Trie字典树实现屏蔽敏感词(UTF-8编码)
前几天写好了字典,又刚好重温了KMP算法,恰逢遇到朋友吐槽最近被和谐的词越来越多了,于是突发奇想,想要自己实现一下敏感词屏蔽. 基本敏感词的屏蔽说起来很简单,只要把字符串中的敏感词替换成"* ...
- [LeetCode] Implement Trie (Prefix Tree) 实现字典树(前缀树)
Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs ar ...
- 萌新笔记——C++里创建 Trie字典树(中文词典)(一)(插入、遍历)
萌新做词典第一篇,做得不好,还请指正,谢谢大佬! 写了一个词典,用到了Trie字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...
- 字典树 - A Poet Computer
The ACM team is working on an AI project called (Eih Eye Three) that allows computers to write poems ...
- poj 2503:Babelfish(字典树,经典题,字典翻译)
Babelfish Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 30816 Accepted: 13283 Descr ...
- hdu 1247:Hat’s Words(字典树,经典题)
Hat’s Words Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- hdu 1075:What Are You Talking About(字典树,经典题,字典翻译)
What Are You Talking About Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/204800 K ...
随机推荐
- vue兄弟组件传值——事件总线
1.创建一个js文件,例如msg.js,放到合适位置,例如components中,或者其他位置也行.然后在兄弟两个组件中分别引入msg.js文件 msg.js: import Vue from 'vu ...
- Go Web 编程之 静态文件
概述 在 Web 开发中,需要处理很多静态资源文件,如 css/js 和图片文件等.本文将介绍在 Go 语言中如何处理文件请求. 接下来,我们将介绍两种处理文件请求的方式:原始方式和http.File ...
- linux下文件解压缩中文乱码问题的解决
将带中文文件名的压缩文件上传到服务器,使用unzip解压后,文件名乱码: 临时解决方法: 通过unzip行命令解压,指定字符集unzip -O CP936 xxx.zip (用GBK, GB18030 ...
- cogs 2. 旅行计划 dijkstra+打印路径小技巧
2. 旅行计划 ★★ 输入文件:djs.in 输出文件:djs.out 简单对比时间限制:3 s 内存限制:128 MB [题目描述] 过暑假了,阿杜准备出行旅游,他已经查到了某些城市 ...
- DateTime.Now
// 2008年4月24日 System.DateTime.Now.ToString( " D " );// 2008-4-24 System.DateTime.Now.ToStr ...
- vue学习笔记2:藕断丝连的 v-show 和 v-if
一.知识点 vue指令 v-show v-if 二.代码案例 v-show <div v-show="isShow">动态显示或隐藏</div> <! ...
- P4513 小白逛公园 动态维护最大子段和
题目链接:https://www.luogu.org/problem/P4513 #include<iostream> #include<cstdio> #include< ...
- Python思维导图(二)—— 数据类型
============================================== =========可点击图片, 放大查看更清晰哦!========= ===========有任何错误请及 ...
- 一起来学习XPATH,来看看除了正则表达式我们还能怎么抓取数据
参考学习的网站链接http://www.w3school.com.cn/xpath/xpath_intro.asp 首先理清楚一些常识 以此为例 <?xml version="1.0& ...
- PythonI/O进阶学习笔记_11.python的多进程
content: 1. 为什么要多进程编程?和多线程有什么区别? 2. python 多进程编程 3. 进程间通信 ======================================= ...