动态规划-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 ...
随机推荐
- ES6学习笔记之变量的解构赋值
变量的解构赋值 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构. 数组的解构赋值 以前,为变量赋值,只能直接指定值: 1 2 3 var a = 1; var b = 2; ...
- AI入门之KNN算法学习
一.什么是KNN算法 kNN(k-NearestNeighbor),也就是k最近邻算法.顾名思义,所谓K最近邻,就是k个最近的邻居的意思.也就是在数据集中,认为每个样本可以用离他最距离近的k个邻居来代 ...
- linux 下修改最大文件数
环境为centosV7系列 1.查看进程的打开最大文件数,默认为1024 [root@localhost ~]# ulimit -a core file size (blocks, -c) 0 dat ...
- Angular 从入坑到挖坑 - 表单控件概览
一.Overview angular 入坑记录的笔记第三篇,介绍 angular 中表单控件的相关概念,了解如何在 angular 中创建一个表单,以及如何针对表单控件进行数据校验. 对应官方文档地址 ...
- 从头认识js-js客户端检测
常用的客户端检测方式有以下三种: 1.能力检测 2.怪癖检测 3.用户代理检测 能力检测 最常用也是最为人们广泛接受的客户端检测形式是能力检测(又称特性检测).能力检测的目标不是识别特定的浏览器,而是 ...
- Apollo 高可用配置中心搭建教程
Apollo开源文档中搭建流程讲的很详细,此处只提供传送门 1.Apollo配置中心开源地址 2.服务包下载地址 3.教程文档地址 4.视频教程地址 5.Apollo使用指南 说明: apollo-c ...
- 一起了解 .Net Foundation 项目 No.16
.Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. Orchard CMS O ...
- mongodb忘记密码处理步骤
mongodb忘记密码的处理办法较MySQL等数据库而言方法显得更加暴力,处理方式如下: 1. 修改mongodb的配置文件 mongodb的配置文件一般可以通过查看进程的方式查看文件名,例如: p ...
- 日常破解--XCTF easy_apk
一.题目来源 来源:XCTF社区安卓题目easy_apk 二.破解思路 1.首先运行一下给的apk,发现就一个输入框和一个按钮,随便点击一下,发现弹出Toast验证失败.如下图所示: ...
- Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式
一.前言 上一篇我分享了一篇关于 Asp.Net Core 中IdentityServer4 授权中心之应用实战 的文章,其中有不少博友给我提了问题,其中有一个博友问我的一个场景,我给他解答的还不够完 ...