最短超级串
难度:
标签:
题目描述
代码结果
运行时间: 341 ms, 内存: 17.4 MB
/*
* 思路:
* 1. 使用回溯法生成所有字符串的排列组合。
* 2. 使用Java Stream对每一个排列组合,检查是否每个字符串都是该组合的子字符串。
* 3. 返回满足条件的最短组合。
*/
import java.util.*;
import java.util.stream.Collectors;
public class Solution {
public String shortestSuperstring(String[] words) {
List<String> permutations = new ArrayList<>();
permute(words, 0, permutations);
return permutations.stream()
.filter(perm -> isValid(perm, words))
.min(Comparator.comparingInt(String::length))
.orElse("");
}
private void permute(String[] words, int start, List<String> result) {
if (start == words.length - 1) {
result.add(String.join("", words));
} else {
for (int i = start; i < words.length; i++) {
swap(words, i, start);
permute(words, start + 1, result);
swap(words, i, start);
}
}
}
private void swap(String[] words, int i, int j) {
String temp = words[i];
words[i] = words[j];
words[j] = temp;
}
private boolean isValid(String superstring, String[] words) {
return Arrays.stream(words).allMatch(superstring::contains);
}
}
解释
方法:
这个题解使用了动态规划的方法来解决问题。首先,我们需要构建一个图 g,其中 g[i][j] 表示将单词 j 接在单词 i 后面时可以省略的最大字符数。然后,我们使用一个动态规划数组 dp 来记录到达每个状态的最大省略字符数。状态由一个整数表示,该整数的二进制形式的每一位表示一个单词是否已经在超级串中。我们逐步构建这个超级串,每次在当前状态下添加一个新的单词,并更新 dp 数组。最后,我们通过回溯 dp 数组来构建最终的超级串。
时间复杂度:
O(n^2 * l + n^2 * 2^n)
空间复杂度:
O(n^2 + n)
代码细节讲解
🦆
在构建图g时,你是如何确定单词j可以接在单词i后面并省略最大字符数的?具体是通过什么逻辑实现的?
▷🦆
动态规划数组dp的定义是什么?dp[i][j]表示的意义是什么?
▷🦆
为什么在更新dp数组时,需要计算每个状态的前一个状态pi和当前单词k的组合?这样的逻辑是基于什么考虑?
▷