动态规划-TSP问题-最短超级串
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问题-最短超级串的更多相关文章
- [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. ...
- [bzoj1195][HNOI2006]最短母串_动态规划_状压dp
最短母串 bzoj-1195 HNOI-2006 题目大意:给一个包含n个字符串的字符集,求一个字典序最小的字符串使得字符集中所有的串都是该串的子串. 注释:$1\le n\le 12$,$1\le ...
- 【33.28%】【BZOJ 1195】[HNOI2006]最短母串
Time Limit: 10 Sec Memory Limit: 32 MB Submit: 1208 Solved: 402 [Submit][Status][Discuss] Descript ...
- bzoj 1195: [HNOI2006]最短母串 爆搜
1195: [HNOI2006]最短母串 Time Limit: 10 Sec Memory Limit: 32 MBSubmit: 894 Solved: 288[Submit][Status] ...
- 2782: [HNOI2006]最短母串
2782: [HNOI2006]最短母串 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 3 Solved: 2[Submit][Status][Web ...
- BZOJ1195[HNOI2006]最短母串——AC自动机+BFS+状态压缩
题目描述 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 输入 第一行是一个正整数n(n<=12),表示给定的字符串的 ...
- BZOJ 1195: [HNOI2006]最短母串
1195: [HNOI2006]最短母串 Time Limit: 10 Sec Memory Limit: 32 MBSubmit: 1346 Solved: 450[Submit][Status ...
- P2322 [HNOI2006]最短母串问题
P2322 [HNOI2006]最短母串问题 AC自动机+bfs 题目要求:在AC自动机建的Trie图上找到一条最短链,包含所有带结尾标记的点 因为n<12,所以我们可以用二进制保存状态:某个带 ...
- [HNOI2006]最短母串问题
题目大意:给定一个字符串集,求一个最短字串,使得该集合内的串都是该串的一个子串 算法:AC自动机+最短路+状压DP 注意空间限制 #include"cstdio" #include ...
随机推荐
- 微信小程序配置二
tabBar 客户端窗口底部的tab页面切换,只能配置最好两个.最多5个tab 属性说明: 属性 类型 必填 默认值 描述 color HexColor 是 tab上的文字默认颜色 selectedC ...
- python常用魔术方法概览
构造和初始化 __init__(self, args) 构造函数 __new__(cls) 传入的是类实例 __del__(self) 析构函数,调用 del cls 时会被调用 属性访问控制 __g ...
- OpenCV3入门(十一)图像直方图
1.直方图的概念 灰度直方图是灰度级的函数,描述的是图像中具有该灰度级的像元的个数.确定图像像素的灰度值范围,以适当的灰度间隔为单位将其划分为若干等级,以横轴表示灰度级,以纵轴表示每一灰度级具有的像素 ...
- Liferay7 Intellij IDEA 开发环境搭建
一.安装Liferay插件 安装过程不在赘述,推荐两种安装方式: 通过Intellij插件市场安装 通过下载插件zip包安装 安装完成后,在项目板块中点鼠标右键,会出现Liferay菜单. 二.安装L ...
- Sublime Text3 旧版本下载以及破解激活方式
前言 当前Sublime Text3 出到了32**版本,以前直接输入激活码的方法已经不能使用. 而官网又不提供旧版本的下载链接,因此在此分享旧版本下载方式以及激活方式. 下载方法 通过下面这个链接下 ...
- 学习Vue.js-Day2
书接上文/思考反馈 react,ng,vue作用差不多,那各个都有什么特点啊,实际工作中应该用哪一个? 答:其实在实际工作中,组员会通过讨论而选择框架:这三个框架都能解放你的工作量,也适合做单页面应用 ...
- OC和C++混编需要注意的问题
文章首发于github.io 2018-12-17 21:01:55 方案一 1. .c文件的identify and type右边栏修改为Objective-C source 2. Built se ...
- 第一个Hystrix程序 Hystrix 一
1.导入jar包 <dependencies> <dependency> <groupId>com.netflix.hystrix</groupId> ...
- Asp.NET MvC EF实现分页
打开Visual Studio 2017 选择 项目----->管理nuget包 其他版本也有 输入paged 下载安装 pagedList和pagedList.mvc 在model文件新建一 ...
- django 从零开始 3认识url解析
在视图函数中定义一个函数abc 接受得到的参数 并显示在页面上 urls中设置 在页面会显示出错误 找不到该url ,原因是django1版本中使用的是url和re_path ,突然django2变 ...