问题描述
字母(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 ...
随机推荐
-
centos 6 安装配置openvpn
下载地址:http://swupdate.openvpn.org/community/releases/http://www.oberhumer.com/opensource/lzo/download ...
-
Node.js Express 框架
Node.js Express 框架 Express 简介 Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP ...
-
Eclipse 配置Activiti插件
Eclipse 配置Activiti插件 我使用的是Eclipse LUNA 4.4.0 点击Eclipse上方工具栏[Help]选择[Install New Software] 在弹出的窗口点击[A ...
-
RCU-数据库初始化参数
C:\Windows\System32>sqlplus sys/As123456 as sysdba SQL> show parameter processes; SQL> shut ...
-
iOS - (利用/调用系统定位获取当前经纬度与地理信息)
这些天做iOS项目的时候,需要通过定位来拿到当期城市的名称.百度地图SDK有这个功能,但为了不依赖第三方,这里使用iOS自带框架CoreLocation来实现这个需求.iOS8出来之后,针对定位需要多 ...
-
xunsearch迅搜体验
安装与启动 http://www.xunsearch.com/doc/php/guide/start.installation 编写配置文件 http://www.xunsearch.com/doc/ ...
-
selenium python (三)鼠标事件
# -*- coding: utf-8 -*-#鼠标事件 #ActionChains类中包括: # context_click() 右击: ...
-
JS多语种方式
方案: 在不同的移动平台(IOS.Android)上,并建立了HTML页面通信框架.主要业务逻辑HTML发展:我要支持多语言开发. 动机: 通过积极主动的信息方式,前一页完成初始化,获取当前语言选项. ...
-
zepto源码分析系列
如果你也开发移动端web,如果你也用zepto,应该值得你看看.有问题请留言. Zepto源码分析-架构 Zepto源码分析-zepto(DOM)模块 Zepto源码分析-callbacks模块 Ze ...
-
PL/SQL学习笔记之基本块格式与语法
一:PL/SQL程序块 PL/SQL是一种块结构的语言,一个PL/SQL程序就是一个 代码逻辑块. PL/SQL程序由三部分构成: 1 声明 部分 使用关键字DECLARE开头,它是一个可选的部分,用 ...