博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[CodeForces-178F]Representative Sampling
阅读量:6795 次
发布时间:2019-06-26

本文共 1463 字,大约阅读时间需要 4 分钟。

题目大意:

  给你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,然后就把它废弃掉。
  这就相当于动态开数组。
  这样就同时解决了时间和空间上的问题。

1 #include
2 #include
3 #include
4 const int inf=0x7fffffff; 5 const int N=2000,K=2001; 6 std::string s[N]; 7 int n,k,lcp[N]; 8 int f[N<<1][K],cnt; 9 void dp(const int &l,const int &r,const int &id) {10 if(l==r) return;11 int mid=0;12 for(register int i=l+1;i<=r;i++) {13 if(lcp[i]
mid-l) break;21 for(register int j=0;j<=k;j++) {22 if(j>r-mid+1) break;23 if(i+j<=k) f[id][i+j]=std::max(f[id][i+j],f[lid][i]+f[rid][j]+lcp[mid]*i*j);24 }25 }26 cnt-=2;27 }28 int main() {29 std::ios_base::sync_with_stdio(false);30 std::cin.tie(NULL);31 std::cin>>n>>k;32 for(register int i=0;i
>s[i];34 }35 std::sort(&s[0],&s[n]);36 lcp[0]=inf;37 for(register int i=1;i

 

转载于:https://www.cnblogs.com/skylee03/p/7701232.html

你可能感兴趣的文章
MTD应用学习:mtd和mtdblock的区别
查看>>
如何使用分布是缓存Hazelcast
查看>>
Spark-ML-01-小试spark分析离线商品信息
查看>>
【hadoop】 running beyond virtual memory错误原因及解决办法
查看>>
5G概念炒的火热,公共WiFi建设却为何不见进展?
查看>>
c/c++中指针学习的两个绝好例子
查看>>
天云郭宏:谈传统IDC困境 指点云建设
查看>>
云计算的最大问题是安全还是隐私?
查看>>
PDMS call Operating System Command
查看>>
如何取消codeblocks对msvcr100.dll的依赖?
查看>>
Jack Ma 你当初UT了没?
查看>>
IBM联手传智播客 落地大数据应用人才培养计划
查看>>
爱尔兰地方议会再次否决一光伏发电项目
查看>>
Appinions:IDC对物联网影响力位居前三
查看>>
《网络空间欺骗:构筑欺骗防御的科学基石》一2.4 集成化网络空间欺骗与计算机防御框架...
查看>>
渤海银行双活数据中心建设值得中小银行借鉴
查看>>
赛普拉斯推出业内首款专为IoT设计的微控制器架构PSoC 6
查看>>
中国人工智能学会通讯——互联网搜索技术的前沿探索 2 文本内容建模
查看>>
如何将数据可视化技术应用于广告投放?
查看>>
有工程师思维吗?什么是工程师思维?
查看>>