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 ...
随机推荐
- surging 社区版本支持.net core 3.1
简介 surging 经过两年多的研发,微服务引擎已经略有雏形,也承蒙各位的厚爱, GitHub上收获了将近2800星,fork 811,付费用户企业也有十几家,还有咨询培训, 在2020年,我们将依 ...
- es lucene搜索及聚合流程源码分析
本文以TermQuery,GlobalOrdinalsStringTermsAggregator为例,通过代码,分析es,lucene搜索及聚合流程.1:协调节点收到请求后,将search任务发到相关 ...
- 小白学Java:包装类
目录 小白学Java:包装类 包装类的继承关系 创建包装类实例 自动装箱与拆箱 自动装箱 自动拆箱 包装类型的比较 "=="比较 equals比较 自动装箱与拆箱引发的弊端 自动装 ...
- cesium加载WFS服务(GeoServer发布)
需求: 为了便于前端渲染数据,自定义图层渲染. 思路: 获取地图服务中的要素进行渲染. 工具: GeoServer 2.6.4,cesium, 思路有了就开始找资料写代码,cesium有接口可以加载W ...
- 79.纯 CSS 创作单元素麦当劳金拱门 Logo(自创)
效果地址:https://scrimba.com/c/cN3P6nfr 原理:两个椭圆,颜色部分为边框,下一半被伪元素覆盖. 感想:看了一眼大神的,代码比我的还少,得研究研究去. HTML code: ...
- 小程序中button标签的open-type属性
open-type (微信开放能力):合法值中的其中之一: getUserInfo 说明:引导用户授权 而获取用户信息,可以从bindgetuserinfo回调中获取到用户信息 而按钮的bi ...
- Linux.cp命令总提示是否覆盖
执行cp命令,其实是默认执行了cp -i命令的别名,因此总提示是否覆盖. 修改~/.bashrc,注释“alias cp='cp -i'”即可. [root@xxxx test]# vi ~/.bas ...
- Java并发关键字Volatile 详解
Java并发关键字Volatile 详解 问题引出: 1.Volatile是什么? 2.Volatile有哪些特性? 3.Volatile每个特性的底层实现原理是什么? 相关内容补充: 缓存一致性协议 ...
- Ubuntu中部署Django项目的配置与链接MySQL
Django的简介 MVT模式的介绍创建项目的虚拟环境 本次使用的是pip安装 一.更新 sudo apt update 二.安装pip sudo apt install python3-pip 三. ...
- centos7的新特性
1.修改主机名方式改变 centos6在/etc/ centos7使用命令hostnamectl set-hostname 主机名2.修改时间方式改变3.查看IP地址ifconfig不再支持改用ip4 ...