jzoj 5001. 【NOI2017模拟3.4】Trie树 状压dp
来源:互联网 发布:画江湖之换世门生知乎 编辑:程序博客网 时间:2024/05/16 07:52
题意
给出n个字符串,每个字符串的字符可以任意调换位置,问将这些字符串建一棵trie树需要的最少节点数(包括根节点)。
n<=16,字符串总长<=10000000
分析
咋一看啥思路都没有,其实并不难,说白了还是我太弱啦。。。
复制一波题解:
显然,如果我们希望 Trie 树的节点数尽量少,我们应该先将所有单词公共的字母拿出
来,作为 Trie 树最上几层的初始链。比如说我们有 aaab,baab 和 cab 三个单词,我们会将
ab 挑出来,然后剩下的单词就变成了 aa,ab,c。
对于剩下的单词,我们将其分成两个子集,(aa,ab)和(c),并分别再计算最长的公
共字母链。显然,当集合中有 n 个单词时,有 2
n种方式将这些单词分成两个子集。
由此,我们可以用状态压缩 dp 解决这个问题。一个状态由单词的子集来描述,也就是
说我们有 2
n个状态,并计算每一种子集形成 Trie 树需要的最少节点数,转移时枚举如何将
子集分裂成两个更小的子集,即可解决整个问题。整个算法总的时间复杂度为
顺带发一波枚举i的子集的方法:for (int j=i;j;j=(j-1)&i);
这样就可以枚举所有i的子集啦。
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define N 35#define inf 0x3f3f3f3fusing namespace std;int bin[N],n,len[N],s[N][30],f[1048580],mn[30];char str[1000005];int main(){ freopen("trie.in","r",stdin);freopen("trie.out","w",stdout); bin[0]=1; for (int i=1;i<=16;i++) bin[i]=bin[i-1]*2; scanf("%d",&n); for (int i=0;i<n;i++) { scanf("%s",str); len[i]=strlen(str); for (int j=0;j<len[i];j++) s[i][str[j]-'a']++; } f[0]=inf; for (int i=1;i<bin[n];i++) { for (int j=0;j<n;j++) if (i&bin[j]) f[i]+=len[j]; memset(mn,inf,sizeof(mn)); for (int j=0;j<n;j++) if (i&bin[j]) for (int k=0;k<26;k++) mn[k]=min(mn[k],s[j][k]); int mx=0; for (int j=0;j<26;j++) mx+=mn[j]; for (int j=i;j;j=(j-1)&i) f[i]=min(f[i],f[j]+f[i-j]); if (mx<f[i]) f[i]-=mx; } printf("%d",f[bin[n]-1]+1); return 0;}
0 0
- jzoj 5001. 【NOI2017模拟3.4】Trie树 状压dp
- jzoj 5040. 【NOI2017模拟4.2】押韵 trie树+树形dp
- jzoj 5026. 【NOI2017模拟3.19】Number 状压dp+大整数分解
- jzoj 5006. 【NOI2017模拟3.8】A 树形dp
- jzoj 5000. 【NOI2017模拟3.4】保镖 hall定理+搜索
- jzoj 5015. 【NOI2017模拟3.15】决斗 贪心+平衡树
- jzoj 5020. 【NOI2017模拟3.17】牛奶装瓶 线段树
- jzoj 5039. 【NOI2017模拟4.2】查询 线段树
- 【JZOJ 100019】【NOI2017模拟6.26】A
- JZOJ 100019【NOI2017模拟6.26】A
- JZOJ 5043. 【NOI2017模拟4.4】保持平衡
- jzoj 4996. 【NOI2017模拟3.1】游戏 扫描线+treap
- jzoj 5012. 【NOI2017模拟3.13】远行 启发式合并
- jzoj 5023. 【NOI2017模拟3.18】Squence 莫队算法
- jzoj 5045. 【NOI2017模拟4.5】无限棋盘 hash+倍增
- 【NOI2017模拟4.5】机器人游戏【搜索,DP】
- 【NOI2017模拟.4.1】Shoes【DP决策单调性,主席树,分治】
- jzoj 4702. 【GDOI2017模拟8.15】Game 状压dp+减枝
- Firefox在input标签padding上下边距过大时的bug现象
- MERGE语句用来合并UPDATE和INSERT语句,一张表的大数据操作,要同时进行增删改,提高性能
- 中国剩余定理(非互质)hdu3579 Hello Kiki ====注意刚好全部整除的情况
- Leetcode twosum
- 安装SQuirrel SQL Client连接Phoenix操作HBase
- jzoj 5001. 【NOI2017模拟3.4】Trie树 状压dp
- 利用摄像头拍照并保存
- 一个基于Behave框架的http接口测试实例
- C语言:顺序表
- Java常用设计模式
- 算法入门---java语言实现的冒泡排序小结
- [点分治 离线] BZOJ 4449 [Neerc2015]Distance on Triangulation
- PCA
- 1066. 图像过滤(15)