NKOJ4191 Trie树
问题描述
字母(Trie)树是一个表示一个字符串集合中所有字符串的前缀的数据结构,其有如下特征:
1.树的每一条边表示字母表中的一个字母
2.树根表示一个空的前缀
3.树上所有其他的节点都表示一个非空前缀,每一个节点表示的前缀为树根到该节点的路径上所有字母依次连接而成的字符串。
4.一个节点的所有出边(节点到儿子节点的边)中不存在重复的字母。
现在Matej手上有N个英文小写字母组成的单词,他想知道,如果将这N个单词中的字母分别进行重新排列,形成的字母树的节点数最少是多少。
输入格式
第一行包含一个正整数N(1<=N<=16)
接下来N行每行一个单词,每个单词都由小写字母组成。
单词的总长度不超过1,000,000。
输出格式
输出仅一个正整数表示N个单词经过重新排列后,字母树的最少节点数。
样例输入
10
jgda
dbfdjj
hehegdfh
faeejic
acagdgfcjc
jifiigdbif
fdbdii
ch
c
adccdd
样例输出
42
显然,如果我们希望Trie树的节点数尽量少,我们应该先将所有单词公共的字母拿出
来,作为Trie树最上几层的初始链。比如说我们有aaab,baab和cab三个单词,我们会将
ab挑出来,然后剩下的单词就变成了aa,ab,c。
对于剩下的单词,我们将其分成两个子集,(aa,ab)和(c),并分别再计算最长的公
共字母链。显然,当集合中有n个单词时,有2^n种方式将这些单词分成两个子集。
由此,我们可以用状态压缩dp解决这个问题。一个状态由单词的子集来描述,也就是
说我们有2^n个状态,并计算每一种子集形成 Trie树需要的最少节点数,转移时枚举如何将
子集分裂成两个更小的子集,即可解决整个问题。整个算法总的时间复杂度为 O(3^n)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int tmp[],n,f[<<];
int vis[][],len[];
char s[][];
int cal(int S)
{int i,j;
memset(tmp,/,sizeof(tmp));
for (i=;i<=n;i++)
{
if (S&(<<i-))
{
for (j=;j<;j++)
{
tmp[j]=min(tmp[j],vis[i][j]);
}
}
}
int as=;
for (i=;i<;i++)
as+=tmp[i];
return as;
}
int dfs(int S)
{int i;
if (S==) return ;
if (S==(S&(-S))) return len[S&(-S)];
if (f[S]!=-) return f[S];
int pre=cal(S),as=1e9;
for (i=(S-)&S;i;i=(i-)&S)
{
as=min(as,dfs(i)+dfs(S^i)-pre);
}
return f[S]=as;
}
int main()
{int i,j;
cin>>n;
memset(f,-,sizeof(f));
for (i=;i<=n;i++)
{
scanf("%s",s[i]);
len[<<i-]=strlen(s[i]);
for (j=;j<len[<<i-];j++)
{
vis[i][s[i][j]-'a']++;
}
}
dfs((<<n)-);
cout<<f[(<<n)-]+;
}
NKOJ4191 Trie树的更多相关文章
- 基于trie树做一个ac自动机
基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...
- 基于trie树的具有联想功能的文本编辑器
之前的软件设计与开发实践课程中,自己构思的大作业题目.做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改.github:https://github.com/chu ...
- hihocoder-1014 Trie树
hihocoder 1014 : Trie树 link: https://hihocoder.com/problemset/problem/1014 题意: 实现Trie树,实现对单词的快速统计. # ...
- 洛谷P2412 查单词 [trie树 RMQ]
题目背景 滚粗了的HansBug在收拾旧英语书,然而他发现了什么奇妙的东西. 题目描述 udp2.T3如果遇到相同的字符串,输出后面的 蒟蒻HansBug在一本英语书里面找到了一个单词表,包含N个单词 ...
- 通过trie树实现单词自动补全
/** * 实现单词补全功能 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #incl ...
- #1014 Trie树
本题主要是求构造一棵Trie树,即词典树用于统计单词. C#代码如下: using System; using System.Collections.Generic; using System.Lin ...
- Trie树-字典查找
描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一本词典,于是小Hi就向小Ho提出了那个经典的问题: ...
- Trie树的创建、插入、查询的实现
原文:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=28977986&id=3807947 1.什么是Trie树 Tr ...
- Trie树(c++实现)
转:http://www.cnblogs.com/kaituorensheng/p/3602155.html http://blog.csdn.net/insistgogo/article/detai ...
随机推荐
- Alpha第八天
Alpha第八天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...
- c++第0次作业
1.你认为大学的学习生活.同学关系.师生应该是怎样? 随着大学生活的慢慢到来,我开始领悟到大学并不是自由的天堂,相反,我们更加的走进社会这个牢笼.在这个牢笼中有着从前的我们并不需要在意和考虑的规则与问 ...
- 冲刺NO.1
Alpha冲刺第一天 站立式会议 项目进展 项目的第一天,主要工作是对项目的开发进行规划,以及将规划的成果转化为燃尽图与博客文章.依据项目需求分析报告与开题报告中已经完成的设计任务和项目规划,我们将系 ...
- centos7 下通过nginx+uwsgi部署django应用
1. 安装python3.6 1. 获取 wget https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tgz tar -xzvf Python- ...
- Flask 扩展 缓存
如果同一个请求会被多次调用,每次调用都会消耗很多资源,并且每次返回的内容都相同,就该使用缓存了 自定义缓存装饰器 在使用Flask-Cache扩展实现缓存功能之前,我们先来自己写个视图缓存装饰器,方便 ...
- Spring Boot jar包linux服务器部署
Spring Boot 部署 一.使用命令行java -jar 常驻 nohup java -jar spring-boot-1.0-SNAPSHOT.jar > log.file 2>& ...
- Node.js系列文章:编写自己的命令行界面程序(CLI)
CLI的全称是Command-line Interface(命令行界面),即在命令行接受用户的键盘输入并作出响应和执行的程序. 在Node.js中,全局安装的包一般都具有命令行界面的功能,例如我们用于 ...
- SourceTree 实现 git flow 流程
为什么使用 git 和 git flow,这篇文章 深入理解学习Git工作流 的内容相信能够给你一个完整的答案. 我们以使用SVN的工作流来使用git有什么不妥? git 方便的branch在哪里,团 ...
- nyoj 韩信点兵
描述相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排.五人一排.七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了.输入3个非负整数a,b,c ,表示每种队形排尾的人数 ...
- JAVA_SE基础——19.数组的定义
数组是一组相关数据的集合,数组按照使用可以分为一维数组.二维数组.多维数组 本章先讲一维数组 不同点: 不使用数组定义100个整形变量:int1,int2,int3;;;;;; 使用数组定义 int ...