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. Linux sed命令实例解析

    最近看project的makefile,又见到了sed的强大编辑能力,在makefile工作之前,通常都是执行脚本或者make menuconfig来配置好各种全局变量.sed活动阶段通常在bash ...

  2. yii批量数据插入

    yii框架批量插入数据有两种方法,第一种是循环多次插入和一次批量插入,第一种方法要注意插入数据中间有一次数据插入失败要注意回滚事务 循环插入数据 第一种方法 $model = new User(); ...

  3. Oracle字段

    pl/sql查看当前数据库编码语句:select userenv('language') from dual; 测试结果:数据库字符集编码是utf-8 1.nvarchar2(size) ,size不 ...

  4. acedCommandS 实现pedit命令

    acedCommandS(RTSTR, _T("PEDIT"),                RTSTR, _T("M"),                R ...

  5. 达拉草201771010105《面向对象程序设计(java)》第十六周学习总结

    达拉草201771010105<面向对象程序设计(java)>第十六周学习总结 第一部分:理论知识 1.程序与进程的概念: (1)程序是一段静态的代码,它是应用程序执行的蓝 本. (2)进 ...

  6. Glide源码解析一,初始化

    转载请标明出处:https:////www.cnblogs.com/tangZH/p/12409849.html Glide作为一个强大的图片加载框架,已经被android官方使用,所以,明白Glid ...

  7. [Cts-Verifier]waiver-Camera-ITS-Test

    [问题描述] 工具:Cts-Verifier-9.0-R11.apk 测试Camera ITS Test时,点击该测试项后verifier apk闪退.重新打开后该项未pass变绿. [问题结论] A ...

  8. LVM简介及CentOS7 LVM操作实战

    LVM简介LVM是逻辑盘卷管理(LogicalVolumeManager)的简称,它是Linux环境下对磁盘分区进行管理的一种机制,LVM是建立在硬盘和 分区之上的一个逻辑层,来提高磁盘分区管理的灵活 ...

  9. SpringBoot图文教程14—SpringBoot集成EasyExcel「上」

    有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...

  10. javascript的constructor属性介绍

    之前闲来了解了__proto__和prototype的区别,每个对象都有隐私属性__proto__,而prototype是javascript函数特有的属性.那么constructor属性呢?最近是遇 ...