题目来源:https://leetcode.com/problems/find-the-shortest-superstring/description/

标记难度:Hard

提交次数:3/4

代码效率:2.93% -> 79.31%

题意

有N个字符串,找到最小的字符串S,使得这N个字符串都是S的子串。其中N<=12,字符串的长度<=20。

分析

这道题比赛的时候我没有做出来,但我自认为自己已经找到了正确的解法(确实差不多是正确的),只要再调一小会就能调出来了!结果事实是又花了两天才弄出来。我犯了这些错误:

  • 在搞错了状态变量的范围的同时没有设置好变量的初值
  • 计算两个字符串的overlap的函数少考虑了一种情况

所以就这样了……


我觉得比较简单的方法还是状态压缩DP。[1]dp[mask][i]表示总共包含mask这些字符串,且以A[i]作为结尾的字符串的最小长度(或者最大overlap长度;当字符串都是那么多时,这两者是一样的。然后就可以递推了:dp[mask ^ 1<<j][j] = max(dp[mask][i] + overlap(i, j))。显然,我们事实上可以不用保存具体的字符串(因为有最后一个字符串就够用了),而且可以事先计算出每两个字符串之间的overlap(这样就不需要重复计算)。不过这样就需要最后重建DP过程了……不过字符串处理过程太耗时了,也可以理解……

不过这样做了之后时间效率大大提高了(从1324ms提高到了28ms)

代码

特别慢的那个就不贴了……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
class  {
private:
inline int calcOverlap(const string& s1, const string& s2) {
int start = s1.length() - s2.length();
start = max(0, start);
for (int i = start; i < s1.length(); i++) {
int len = s1.length() - i;
if (s1.substr(i, len) == s2.substr(0, len))
return len;
}
return 0;
} inline bool contains(int cnt, int i) {
return (cnt & (1 << i)) != 0;
}大专栏  Leetcode 943. Find the Shortest Superstring(DP)> public:
string shortestSuperstring(vector<string>& A) {
int n = A.size();
if (n == 1) return A[0]; int overlap[n][n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
overlap[i][j] = calcOverlap(A[i], A[j]); const int MAX_CNT = (1 << n);
int f[MAX_CNT][n], parent[MAX_CNT][n];
for (int i = 0; i < n; i++) {
f[1 << i][i] = 0;
parent[1 << i][i] = -1;
} // start DP
int ans = -1;
int p = -1;
for (int cnt = 2; cnt <= n; cnt++) {
for (int i = 0; i < MAX_CNT; i++) {
if (__builtin_popcount(i) != cnt) continue;
// ends with j
for (int j = 0; j < n; j++) {
if (!contains(i, j)) continue;
f[i][j] = -1; int nmask = i ^ (1 << j);
// last one ends with k
for (int k = 0; k < n; k++) {
if (!contains(nmask, k)) continue;
if (f[nmask][k] + overlap[k][j] > f[i][j]) {
f[i][j] = f[nmask][k] + overlap[k][j];
parent[i][j] = k;
}
} if (cnt == n && f[i][j] > ans) {
ans = f[i][j];
p = j;
}
}
}
} // rebuild the path
string str;
int nmask = MAX_CNT - 1;
while (true) {
int par = parent[nmask][p];
if (par == -1) {
str = A[p] + str;
break;
}
str = A[p].substr(overlap[par][p], A[p].length() - overlap[par][p]) + str;
nmask ^= (1 << p);
p = par;
} return str;
}
};

  1. Leetcode Official Solution for 943. Find the Shortest Superstring

Leetcode 943. Find the Shortest Superstring(DP)的更多相关文章

  1. 由Leetcode详解算法 之 动态规划(DP)

    因为最近一段时间接触了一些Leetcode上的题目,发现许多题目的解题思路相似,从中其实可以了解某类算法的一些应用场景. 这个随笔系列就是我尝试的分析总结,希望也能给大家一些启发. 动态规划的基本概念 ...

  2. 【LeetCode】10.Regular Expression Matching(dp)

    [题意] 给两个字符串s和p,判断s是否能用p进行匹配. [题解] dp[i][j]表示s的前i个是否能被p的前j个匹配. 首先可以分成3大类情况,我们先从简单的看起: (1)s[i - 1] = p ...

  3. LeetCode House Robber 家庭劫犯(dp)

    题意:有一个整数序列,从中挑出一些数字,使得总和是最大,前提是,相邻的两个数字中只能挑其一.比如1 2 3 就只能挑2或者1和3. 思路:很直观的题,dp思想.降低规模,从小规模开始考虑.如果只有两个 ...

  4. Java实现 LeetCode 823 带因子的二叉树(DP)

    823. 带因子的二叉树 给出一个含有不重复整数元素的数组,每个整数均大于 1. 我们用这些整数来构建二叉树,每个整数可以使用任意次数. 其中:每个非叶结点的值应等于它的两个子结点的值的乘积. 满足条 ...

  5. Leetcode之动态规划(DP)专题-详解983. 最低票价(Minimum Cost For Tickets)

    Leetcode之动态规划(DP)专题-983. 最低票价(Minimum Cost For Tickets) 在一个火车旅行很受欢迎的国度,你提前一年计划了一些火车旅行.在接下来的一年里,你要旅行的 ...

  6. Leetcode之动态规划(DP)专题-647. 回文子串(Palindromic Substrings)

    Leetcode之动态规划(DP)专题-647. 回文子串(Palindromic Substrings) 给定一个字符串,你的任务是计算这个字符串中有多少个回文子串. 具有不同开始位置或结束位置的子 ...

  7. Leetcode之动态规划(DP)专题-474. 一和零(Ones and Zeroes)

    Leetcode之动态规划(DP)专题-474. 一和零(Ones and Zeroes) 在计算机界中,我们总是追求用有限的资源获取最大的收益. 现在,假设你分别支配着 m 个 0 和 n 个 1. ...

  8. Leetcode之动态规划(DP)专题-486. 预测赢家(Predict the Winner)

    Leetcode之动态规划(DP)专题-486. 预测赢家(Predict the Winner) 给定一个表示分数的非负整数数组. 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端 ...

  9. Leetcode之动态规划(DP)专题-264. 丑数 II(Ugly Number II)

    Leetcode之动态规划(DP)专题-264. 丑数 II(Ugly Number II) 编写一个程序,找出第 n 个丑数. 丑数就是只包含质因数 2, 3, 5 的正整数. 示例: 输入: n ...

随机推荐

  1. Android如何制作自己的依赖库上传至github供别人下载使用

    Android如何制作自己的依赖库上传至github供别人下载使用 https://blog.csdn.net/xuchao_blog/article/details/62893851

  2. top 命令中的VIRT,RES,SHR ,MEM区别

    VIRT 表示进程的虚拟(地址)空间大小,其包含进程实际使用的大小(申请的堆栈), 使用mmap映射的大小,包括外设RAM, 还有映射到本进程的文件(例如动态库),还有进程间的共享内存.所以VIRT ...

  3. js window.onload 加载多个函数和追加函数

    平时做项目 经常需要使用window.onload, 用法如下: function func(){alert("this is window onload event!");ret ...

  4. 吴裕雄--天生自然C语言开发:函数指针

    #include <stdio.h> int max(int x, int y) { return x > y ? x : y; } int main(void) { /* p 是函 ...

  5. 四剑客(awk)

    AWK AWK简介 虽然sed编辑器是非常方便自动修改文本文件的工具,但其也有自身的限制.通常你需要一个用来处理文件中的数据的更高级工具,它能提供一个类编程环境来修改和重新组织文件中的数据.这正是ga ...

  6. winfrom控件圆角

    刚好用到这个功能,看了好些例子.我就不明白,简单的一个事,一些文章里的代码写的那个长啊,还让人看么. 精简后,就其实一点,只要有paint事件的组件,都可画圆角,没有的外面套一个panel就行了. u ...

  7. 对数据集进行最优分箱和WOE转换

    对数据集分箱的方式三种,等宽等频最优,下面介绍对数据集进行最优分箱,分箱的其他介绍可以查看其他的博文,具体在这就不细说了: 大体步骤: 加载数据: 遍历所有的feature, 分别处理离散和连续特征: ...

  8. HTTP Status 400,400 (Bad Request)

    400 (Bad Request) 点击添加按钮转跳没反应,控制台没报错,然后在Chrome上检查发现报错了 百度了一下,发现http Status 400这个错误大多是因为,jsp的form表单提交 ...

  9. CSS-----样式表案例(沃顿商学院)之高级山寨版

    HTML-CSS设计----------沃顿商学院(高级山寨版) 1.html代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Trans ...

  10. golang kafka clinet 内存泄露问题处理

    go 内存泄露 新版本服务跑上一天内存占用20g,显然是内存泄露 内存泄露的问题难在定位 技术上的定位 主要靠 pprof 生成统计文件 之前写web项目 基于net/http/pprof 可以看到运 ...