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 ...
随机推荐
- 听翁恺老师mooc笔记(10)--结构
定义结构: 在程序里,如果想要表达一个数据就需要一个变量,而每个变量又都需要一个类型,之前学过C语言中有int.double.float.char等这些基础类型,还有指针.数组等.如果你要表达的数据比 ...
- 《结对-HTML贪吃蛇游戏项目-测试过程》
项目托管平台地址:https://gitee.com/zhaojianhuiAA/TanChiShe/blob/master/snake.html 项目成员:赵建辉.马壮. 测试: 1.界面:用jav ...
- bug终结者 团队作业第一周
bug终结者 团队作业第一周 小组组员及人员分工 小组成员 组长: 20162323 周楠 组员: 20162302 杨京典 20162322 朱娅霖 20162327 王旌含 20162328 蔡文 ...
- SQL的介绍及MySQL的安装
基础篇 - SQL 介绍及 MySQL 安装 SQL的介绍及MySQL的安装 课程介绍 本课程为实验楼提供的 MySQL 实验教程,所有的步骤都在实验楼在线实验环境中完成, ...
- XML之自动生成类,添加,修改,删除类的属性
1. class ClassHelperDemo { public static void Main() { #region 演示一:动态生成类. //生成一个类t. Type t = ClassHe ...
- 面向对象的PHP(5)
OOP的好处 封装 封装可以隐藏实现细节,使代码模块化,代码重用 继承 继承可以扩展已存在的代码模块(class),代码重用 多态 为了类在继承和派生的时候,保证实例的某一属性正确调用,接口重用 关键 ...
- 计算机基础,Python基础--变量以及简单的循环
一.计算机基础 1.CPU 相当于人体的大脑,用于计算处理数据. 2.内存 用于存储数据,CPU从内存调用数据处理计算,运算速度很快. PS:问:既然在内存里的数据CPU运算速度快,为什么计算机不全 ...
- Java8新特性第2章(接口默认方法)
在Java中一个接口一旦发布就已经被定型,除非我们能够一次性的更新所有该接口的实现,否者在接口的添加新方法将会破坏现有接口的实现.默认方法就是为了解决这一问题的,这样接口在发布之后依然能够继续演化. ...
- vue.js初识(一)
一 什么是vue? Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不 ...
- Java基础学习(四)-- 接口、集合框架、Collection、泛型详解
接口 一.接口的基本概念 关键字为:Interface,在JAVA编程语言中是一个抽象类型,是抽象方法的集合.也是使用.java文件编写. 二.接口声明 命名规范:与类名的命名规范相同,通常情况下 ...