题目大意:
  给你n个字符串,要求从中选出k个字符串,使得字符串两两lcp之和最大。

思路:
  动态规划。
  首先将所有的字符串排序,求出相邻两个字符串的lcp长度(很显然,对于某一个字符串,和它lcp最长的字符串一定是和它字典序最接近的一个)。
  接下来考虑一种类似于分治的做法。
  首先找出当前区间内最小的lcp。
  很显然,在这个lcp左边的字符串和右边的字符串配对时的lcp一定是这个lcp。
  假如我们在左边取了i个,右边取了j个,这个lcp对答案的贡献是lcp*i*j。
  接下来递归处理左半边的区间和右半边的区间即可。
  考虑如何表示状态。
  不难想到用f[l][r][k]表示在l~r之间取k个字符串。
  每次递归枚举左右区间取的个数。
  总共有n^2k种状态,如果使用记忆化,很显然数组开不下。
  不使用记忆化则会TLE。
  接下来考虑改进这个状态。
  我们递归的时候不需要针对某一个具体的k,而是在l,r这个状态内枚举k。
  显然,对于同一个l,r,k,只会被转移一次。
  而同一组l,r只会被转移一次。
  因此我们只需要在递归的时候存一下l,r,然后就把它废弃掉。
  这就相当于动态开数组。
  这样就同时解决了时间和空间上的问题。

 #include<string>
#include<iostream>
#include<algorithm>
const int inf=0x7fffffff;
const int N=,K=;
std::string s[N];
int n,k,lcp[N];
int f[N<<][K],cnt;
void dp(const int &l,const int &r,const int &id) {
if(l==r) return;
int mid=;
for(register int i=l+;i<=r;i++) {
if(lcp[i]<lcp[mid]) mid=i;
}
const int lid=cnt++,rid=cnt++;
dp(l,mid-,lid);
dp(mid,r,rid);
__builtin_memset(f[id],,sizeof f[id]);
for(register int i=;i<=k;i++) {
if(i>mid-l) break;
for(register int j=;j<=k;j++) {
if(j>r-mid+) break;
if(i+j<=k) f[id][i+j]=std::max(f[id][i+j],f[lid][i]+f[rid][j]+lcp[mid]*i*j);
}
}
cnt-=;
}
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
std::cin>>n>>k;
for(register int i=;i<n;i++) {
std::cin>>s[i];
}
std::sort(&s[],&s[n]);
lcp[]=inf;
for(register int i=;i<n;i++) {
lcp[i]=std::min(s[i].length(),s[i-].length());
for(register int j=;j<lcp[i];j++) {
if(s[i][j]!=s[i-][j]) {
lcp[i]=j;
}
}
}
dp(,n-,cnt++);
std::cout<<f[][k]<<std::endl;
return ;
}

[CodeForces-178F]Representative Sampling的更多相关文章

  1. [Codeforces178F2]Representative Sampling

    Problem 给定n个字符串Si,任意选出k个字符串Ai,使得其中任意两个字符串lcp之和最大. Solution 建一棵trie树,枚举每一个节点对答案的贡献,树形dp,时间复杂度像是O(N^3) ...

  2. Simple Random Sampling|representative sample|probability sampling|simple random sampling with replacement| simple random sampling without replacement|Random-Number Tables

    1.2 Simple Random Sampling Census, :全部信息 Sampling: 抽样方式: representative sample:有偏向,研究者选择自己觉得有代表性的sam ...

  3. Survey sampling

    Survey sampling \(\bullet\)What is survey sampling?(c.f.census survey)(c.f.:参考,查看,来源于拉丁语) \(\bullet\ ...

  4. 图像抠图算法学习 - Shared Sampling for Real-Time Alpha Matting

    一.序言   陆陆续续的如果累计起来,我估计至少有二十来位左右的朋友加我QQ,向我咨询有关抠图方面的算法,可惜的是,我对这方面之前一直是没有研究过的.除了利用和Photoshop中的魔棒一样的技术或者 ...

  5. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  6. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  7. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  8. 【Codeforces 738A】Interview with Oleg

    http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...

  9. CodeForces - 662A Gambling Nim

    http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...

随机推荐

  1. [CodePlus 2017 11月赛]晨跑 题解(辗转相除法求GCD)

    [CodePlus 2017 11月赛]晨跑 Description "无体育,不清华"."每天锻炼一小时,健康工作五十年,幸福生活一辈子".在清华,体育运动绝 ...

  2. 牛奶ddw如何通过以太坊钱包实现互相打赏

    很多朋友不清楚如何转账ddw,但是万能的网友是无敌的,这两天就自己摸索的一点经验总结下今天的转账经验. 1. 提取到自己的账户 这个大家都知道如何操作,使用官方的钱包 在“日日盈app”中点击&quo ...

  3. js固定小数位数 .toFixed()

    toFixed(num)法可把 Number 四舍五入为指定小数位数的数字. num为需要固定的位数 var num=2;console.log(num.toFixed(2));//2.00;var ...

  4. java网络编程三次握手四次挥手

    第一次握手:client设置syn=1,随机产生一个序列号seq=x,将数据包发送到server.client进入syn_send状态, 等待server确认. 第二次握手:server查看clien ...

  5. 关于U3D中的移动和旋转

    关于移动,其实很简单,就是移动: 第一个参数标识移动的距离,是一个矢量:第二个参数是因为游戏对象有自己的坐标系,还有一个世界坐标系,使用的坐标系不同将导致运动的结果不同: function Trans ...

  6. 创建文件和修改时间戳——touch

    linux的touch命令不常用,一般在使用make的时候可能会用到,用来修改文件时间戳,或者新建一个不存在的文件. 1.命令格式: touch [选项]... 文件... 2.命令参数: -a    ...

  7. 端口扫描———nmap

    nmap教程之nmap命令使用示例(nmap使用方法) 浏览:8268 | 更新:2014-03-29 17:23 Nmap是一款网络扫描和主机检测的非常有用的工具.Nmap是不局限于仅仅收集信息和枚 ...

  8. 产生随机数 random

    int rand(void); 返回 0 ------- RAND_MAX 之间的一个 int 类型整数,该函数为非线程安全函数.并且生成随机数的性能不是很好,已经不推荐使用.        void ...

  9. linux shell 一些命令

    https://stackoverflow.com/questions/918886/how-do-i-split-a-string-on-a-delimiter-in-bash wc: https: ...

  10. go chapter 9 - 反射

    https://www.cnblogs.com/diegodu/p/5590133.html // 反射,根据字段名设置值 package entities import( "reflect ...