2020-03-03 22:55:08

问题描述:

给定一个字符串数组 A,找到以 A 中每个字符串作为子字符串的最短字符串。

我们可以假设 A 中没有字符串是 A 中另一个字符串的子字符串。

示例 1:

输入:["alex","loves","leetcode"]
输出:"alexlovesleetcode"
解释:"alex","loves","leetcode" 的所有排列都会被接受。

示例 2:

输入:["catg","ctaagt","gcta","ttca","atgcatc"]
输出:"gctaagttcatgcatc"

提示:

1 <= A.length <= 12
1 <= A[i].length <= 20

问题求解:

解法一:暴力求解

首先我们要明确的就是,本题可以转化成图论的题目,就是在一个图中要遍历所有的节点一次,最后路径的最小值是多少。(这里和TSP略有不同,即我们不需要返回起始节点)

暴力求解,可以理解为全排列,只不过我们做了一些剪枝操作进行了加速。

时间复杂度:O(n!)

    int res = (int)1e9;
List<Integer> path;
int n; public String shortestSuperstring(String[] A) {
n = A.length;
int[][] graph = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = Math.min(A[i].length(), A[j].length()); k >= 0; k--) {
if (A[j].substring(0, k).equals(A[i].substring(A[i].length() - k))) {
graph[i][j] = A[j].length() - k;
break;
}
}
}
}
helper(A, graph, 0, 0, 0, new ArrayList<>());
StringBuffer sb = new StringBuffer();
for (int i = 0; i < n; i++) {
int node = path.get(i);
String s = A[node];
if (i == 0) sb.append(s);
else sb.append(s.substring(s.length() - graph[path.get(i - 1)][node]));
}
return sb.toString();
} private void helper(String[] A, int[][] graph, int k, int used, int curr, List<Integer> curr_p) {
if (curr >= res) return;
if (k == n) {
res = curr;
path = new ArrayList<>(curr_p);
return;
}
for (int i = 0; i < n; i++) {
if ((used & (1 << i)) != 0) continue;
curr_p.add(i);
helper(A, graph, k + 1, used | (1 << i), k == 0 ? A[i].length() : curr + graph[curr_p.get(curr_p.size() - 2)][i], curr_p);
curr_p.remove(curr_p.size() - 1);
}
}

  

解法二:DP

dp[s][i] : 当前访问过的节点状态为s,且以i为结尾的最短路径。

init :

dp[1 << i][i] = A[i].length()

transition :

对于dp[s][i]我们需要去枚举所有的parent节点,计算得到当前的最小值。

dp[s][i] = min{dp[s - (1 << i)][j] + graph[j][i]) 将A[i]追加到A[j]后面。

时间复杂度:O(2 ^n * n ^ 2)    同TSP问题

    public String shortestSuperstring(String[] A) {
int n = A.length;
int[][] graph = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = Math.min(A[i].length(), A[j].length()); k >= 0; k--) {
if (A[j].substring(0, k).equals(A[i].substring(A[i].length() - k))) {
graph[i][j] = A[j].length() - k;
break;
}
}
}
}
int[][] dp = new int[1 << n][n];
int[][] parent = new int[1 << n][n];
for (int i = 0; i < 1 << n; i++) {
Arrays.fill(dp[i], (int)1e9);
Arrays.fill(parent[i], -1);
}
for (int i = 0; i < n; i++) dp[1 << i][i] = A[i].length();
for (int s = 1; s < 1 << n; s++) {
for (int i = 0; i < n; i++) {
if ((s & (1 << i)) == 0) continue;
int prev = s - (1 << i);
for (int j = 0; j < n; j++) {
if (dp[prev][j] + graph[j][i] < dp[s][i]) {
dp[s][i] = dp[prev][j] + graph[j][i];
parent[s][i] = j;
}
}
}
}
int curr = -1;
int min = (int)1e9;
for (int i = 0; i < n; i++) {
if (dp[(1 << n) - 1][i] < min) {
min = dp[(1 << n) - 1][i];
curr = i;
}
} int s = (1 << n) - 1;
String res = "";
while (s > 0) {
int prev = parent[s][curr];
if (prev == -1) res = A[curr] + res;
else res = A[curr].substring(A[curr].length() - graph[prev][curr]) + res;
s &= ~(1 << curr);
curr = prev;
} return res;
}

  

动态规划-TSP问题-最短超级串的更多相关文章

  1. [Swift]LeetCode943. 最短超级串 | Find the Shortest Superstring

    Given an array A of strings, find any smallest string that contains each string in A as a substring. ...

  2. [bzoj1195][HNOI2006]最短母串_动态规划_状压dp

    最短母串 bzoj-1195 HNOI-2006 题目大意:给一个包含n个字符串的字符集,求一个字典序最小的字符串使得字符集中所有的串都是该串的子串. 注释:$1\le n\le 12$,$1\le ...

  3. 【33.28%】【BZOJ 1195】[HNOI2006]最短母串

    Time Limit: 10 Sec  Memory Limit: 32 MB Submit: 1208  Solved: 402 [Submit][Status][Discuss] Descript ...

  4. bzoj 1195: [HNOI2006]最短母串 爆搜

    1195: [HNOI2006]最短母串 Time Limit: 10 Sec  Memory Limit: 32 MBSubmit: 894  Solved: 288[Submit][Status] ...

  5. 2782: [HNOI2006]最短母串

    2782: [HNOI2006]最短母串 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 3  Solved: 2[Submit][Status][Web ...

  6. BZOJ1195[HNOI2006]最短母串——AC自动机+BFS+状态压缩

    题目描述 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 输入 第一行是一个正整数n(n<=12),表示给定的字符串的 ...

  7. BZOJ 1195: [HNOI2006]最短母串

    1195: [HNOI2006]最短母串 Time Limit: 10 Sec  Memory Limit: 32 MBSubmit: 1346  Solved: 450[Submit][Status ...

  8. P2322 [HNOI2006]最短母串问题

    P2322 [HNOI2006]最短母串问题 AC自动机+bfs 题目要求:在AC自动机建的Trie图上找到一条最短链,包含所有带结尾标记的点 因为n<12,所以我们可以用二进制保存状态:某个带 ...

  9. [HNOI2006]最短母串问题

    题目大意:给定一个字符串集,求一个最短字串,使得该集合内的串都是该串的一个子串 算法:AC自动机+最短路+状压DP 注意空间限制 #include"cstdio" #include ...

随机推荐

  1. oppo互联网招聘-各类软件测试

    一.服务端测试专家 关键词:安全测试.白盒测试.性能测试.自动化.持续集成.服务端 岗位职责: 主导多个高日活产品的测试方案: 试点和推广自动化和持续集成: 改善测试相关流程和规范. 职位要求: 计算 ...

  2. 算法小练#1 - Dany Yang

    开始记录每周做过的算法题,这是第一周,新的开始 1021. 删除最外层的括号 题目要求如下: 有效括号字符串为空 ("")."(" + A + ")& ...

  3. 开始使用Github

     Gather ye rosebuds while ye may 我自己也是刚开始使用github没几天,写得不好我就写自己常用的吧 2015年9月20日下午3:19更新知乎上这个答案写得好多了

  4. 视频描述(Video Captioning)近年重要论文总结

    视频描述 顾名思义视频描述是计算机对视频生成一段描述,如图所示,这张图片选取了一段视频的两帧,针对它的描述是"A man is doing stunts on his bike", ...

  5. Git私服搭建

    Git私服搭建 一.Git服务器搭建方式 GIT是一个分布式版本管理系统,既然是分布那么必定会涉及远程通信,那么GIT是采用什么协议进行远程通信? Git支持的四种通信协议: Local(本地协议) ...

  6. Java入门教程九(封装继承多态)

    封装 封装就是将对象的属性和方法相结合,通过方法将对象的属性和实现细节保护起来,实现对象的属性隐藏.做法就是:修改属性的可见性来限制对属性的访问,并为每个属性创建一对取值(getter)方法和赋值(s ...

  7. js案例之使用正则表达式进行验证数据正确性

    #js案例之使用正则表达式进行验证数据正确性 代码上传至 "GitHub" 样例: <tr> <td>密码:</td> <td> & ...

  8. 【读书笔记】https://source.android.google.cn/compatibility/tests?hl=en

    AuthorBlog:秋城https://www.cnblogs.com/houser0323/ Android Platform Testing This content is geared tow ...

  9. jdbc对 数据库的数据进行增删改(两个类)

    1.方法类 package com.com; import java.sql.Connection;import java.sql.DriverManager;import java.sql.Resu ...

  10. Java8 新特性2——强大的Stream API

    强大的Stream API Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找.过滤和映射数据等操作.简而言之,Stream API 提供 ...