首页 > 其他分享 >upc 6902: Trie树 (状压dp)

upc 6902: Trie树 (状压dp)

时间:2023-06-02 18:32:21浏览次数:65  
标签:前缀 Trie 字母 状压 upc 单词 字符串 节点 dp


6902: Trie树

时间限制: 1 Sec  内存限制: 128 MB
提交: 137  解决: 19
[提交] [状态] [讨论版] [命题人:admin]

题目描述

字母(Trie)树是一个表示一个字符串集合中所有字符串的前缀的数据结构,其有如下特征:
1.树的每一条边表示字母表中的一个字母
2.树根表示一个空的前缀
3.树上所有其他的节点都表示一个非空前缀,每一个节点表示的前缀为树
根到该节点的路径上所有字母依次连接而成的字符串。
4.一个节点的所有出边(节点到儿子节点的边)中不存在重复的字母。

 

单词“A”“to”“tea”“ted”“ten”“i”“in”“inn”对应的Trie树

现在Matej手上有N个英文小写字母组成的单词,他想知道,如果将这N个单词中的字母分别进行重新排列,形成的字母树的节点数最少是多少。

输入

第一行包含一个正整数N(1<=N<=16)
接下来N行每行一个单词,每个单词都由小写字母组成。
单词的总长度不超过1,000,000。

输出

输出仅一个正整数表示N个单词经过重新排列后,字母树的最少节点数。

样例输入


3 a ab abc


样例输出


4


来源/分类

中山纪念中学20170304 

【小结】

状压dp配字符串。我怎么这么菜

【分析】

如果只有两个字符串(注意我这里形容的字符串字母乱序),abc 和 abe,很明显能找到最长的公共前缀为ab长度2,故答案为3+3-2

对于多个字符串,可分为两组,假设每一组都已经得到了最优值,那么总的最优值就等于这两组值之和减掉最长公共前缀

一直分组,最后一定可以分解成每组一个字符串,合并时,按上述方法取最小值即可。

状压dp把n个物品对应到一个数字二进制的每一个位,为1代表选上,为0代表不选。

【代码】

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX=2e5+5;
const int INF=0x3f3f3f3f;
template<class T>bool gmax(T &a,T b){return a<b?a=b,1:0;}
template<class T>bool gmin(T &a,T b){return a>b?a=b,1:0;}

char str[MAX*5];
int dp[1<<17];
int cnt[17][26]; //每个串中,各字母数量
int c[26];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%s",str);
        for(int j=0;str[j];j++)
            cnt[i][str[j]-'a']++;
    }

    for(int i=0;i<(1<<n);i++) //枚举集合
    {
        dp[i]=0;
        memset(c,0x3f,sizeof(c));
        for(int j=0;j<n;j++)if((1<<j)&i) //枚举i集合内的单词
        {
            for(int ch=0;ch<26;ch++)
            {
                dp[i]+=cnt[j][ch]; //统计当前集合所有字母数,这有可能是最坏情况,没有公共前缀
                gmin(c[ch],cnt[j][ch]); //统计每个字母的最小出现次数,若不为0,则可以作为公共前缀
            }
        }
        int sum=0;
        for(int j=0;j<26;j++)sum+=c[j]; //统计公共前缀的数量
        for(int j=i&i-1;j;j=i&j-1)
            gmin(dp[i],dp[j]+dp[j^i]-sum); //j是i的一个子集,j^i是j的补集,合并后可减掉公共前缀
    }
    printf("%d\n",dp[(1<<n)-1]+1);
}

 

标签:前缀,Trie,字母,状压,upc,单词,字符串,节点,dp
From: https://blog.51cto.com/u_16125110/6404561

相关文章

  • Public Key Retrieval is not allowed
    错误描述:运行spring程序时报错:PublicKeyRetrievalisnotallowed解决:在application.properties文件中在数据库url后加入选项allowPublicKeyRetrieval=true(解决来源)文章地址:https://www.cnblogs.com/lusaisai/p/13372763.html原因未知......
  • Gitlab Registries
    在项目开发和部署过程中,我们常常需要一套私有仓库,比如CodeRepository、PackageRepository,DockerRegistry等。CodeRepository:在github或gitlab或gitee等平台上创建私有项目;或搭建本地代码服务器,一般常用gitlab开源版本搭建。PackageRegistry:以nuget为例,官方nu......
  • couldn't clear tomcat cache java.lang.NoSuchFieldException: resourceEntries
    2015-09-2500:17:11,435WARN[dqapp24http-nio-8002-exec-22]com.opensymphony.xwork2.util.LocalizedTextUtilcouldn'tcleartomcatcachejava.lang.NoSuchFieldException:resourceEntriesatjava.lang.Class.getDeclaredField(Class.java:2062)~[na:1.8......
  • THUPC2023 游记
    五月二十七号上午,我和国家队一行人出发前往北京。说起来这是我第五次来北京了,但上一次来还是在几乎六年前。那时同行的伙伴在我刚上初中时成为了我的好朋友,高中也被分到了一个班,但现在已经没有交流了。我努力回忆着自己对北京的所有印象,但除了很小的时候父亲出差带我到北京玩,其它......
  • THUPC2023 游记
    之前有人说我这个赛季一年都没写过游记,刚好不想卷这次THU之行给我留下了很深印象,所以就来写篇游记浅浅记录一下。和Linshey,chen_03两位强神也是两位老队友组的队,队名叫「联合省选第一年」,源于我们省今年首次加入联合省选。顺带一提,去年我们的队伍名叫「最后的FJOIer」。5.2......
  • poj 1451(Trie)
    题意:就是让你模拟手机输入单词。具体就是给你一些单词,以及该单词被使用的频数,这个频数也是该单词前缀的使用频数,当然不同的单词有可能有相同的前缀,那么这个相同的前缀的使用频数就是这两个单词使用频数之和,以此类推。然后再给你一些数字串,让你针对该数字串的每一个前缀输出它的最有......
  • upc 6888: 守卫(区间dp O(n^2) )
    6888:守卫时间限制:1Sec  内存限制:512MB提交:102  解决:33[提交][状态][讨论版][命题人:admin]题目描述九条可怜是一个热爱运动的女孩子。这一天她去爬山,她的父亲为了她的安全,雇了一些保镖,让他们固定地呆在在山的某些位置,来实时监视九条可怜,从而保护她。具体来......
  • upc 6621: HSI(数学期望,数学推导能力)
    6621:HSI时间限制:1Sec  内存限制:128MB提交:544  解决:112[提交][状态][讨论版][命题人:admin]题目描述Takahashiisnowcompetinginaprogrammingcontest,buthereceivedTLEinaproblemwheretheanswerisYESorNO.Whenhecheckedthedetaileds......
  • upc 6597: Don't Be a Subsequence (字符串的最短不匹配子序列 dp)
    6597:Don'tBeaSubsequence时间限制:1Sec  内存限制:128MB提交:237  解决:45[提交][状态][讨论版][命题人:admin] 题目描述AsubsequenceofastringSisastringthatcanbeobtainedbydeletingzeroormorecharactersfromSwithoutchangingtheor......
  • upc 6445: 棋盘V (网络流费用流解决匹配问题)
    6445:棋盘V时间限制:1Sec  内存限制:128MB提交:325  解决:31[提交][状态][讨论版][命题人:admin]题目描述有一块棋盘,棋盘的边长为100000,行和列的编号为1到100000。棋盘上有n个特殊格子,任意两个格子的位置都不相同。现在小K要猜哪些格子是特殊格子。她知道所有格子......