2021-05-23 Daily-Challenge
Today is Saturday, I gonna review the tasks I've done this week, and finish today's leetcode's May LeetCoding Challenge with cpp
.
May LeetCoding Challenge 23
Description
Find the Shortest Superstring
Given an array of strings words
, return the smallest string that contains each string in words
as a substring. If there are multiple valid strings of the smallest length, return any of them.
You may assume that no string in words
is a substring of another string in words
.
Example 1:
Input: words = ["alex","loves","leetcode"]
Output: "alexlovesleetcode"
Explanation: All permutations of "alex","loves","leetcode" would also be accepted.
Example 2:
Input: words = ["catg","ctaagt","gcta","ttca","atgcatc"]
Output: "gctaagttcatgcatc"
Constraints:
1 <= words.length <= 12
1 <= words[i].length <= 20
words[i]
consists of lowercase English letters.- All the strings of
words
are unique.
Solution
DP
int prefix(string &pre, string &post) {
int lPre = pre.length();
int lPost = post.length();
for(int len = min(lPre, lPost); len; --len) {
bool ok = true;
for(int i = 0; ok && i < len; ++i) {
ok = pre[lPre - len + i] == post[i];
}
if(ok) return len;
}
return 0;
}
class Solution {
int n;
vector<int> len;
vector<vector<int>> overlap;
vector<unordered_map<int, int>> dp;
vector<unordered_map<int, int>> next;
void init(vector<string>& words) {
n = words.size();
dp.resize(n);
len.resize(n);
next.resize(n);
overlap.resize(n, vector<int>(n));
for(int i = 0; i < n; ++i) {
len[i] = words[i].length();
}
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
if(i == j) continue;
overlap[i][j] = prefix(words[i], words[j]);
}
}
}
int solve(int idx, int mask) {
// cout << idx << ' '<< mask<<endl;
if(mask == (1 << n) - 1) return 0;
if(dp[idx].count(mask)) return dp[idx][mask];
dp[idx][mask] = INT_MAX;
for(int i = 0; i < n; i++) {
if(!(mask & (1 << i))) {
int tmp = len[i] - overlap[idx][i] + solve(i, mask | (1 << i));
if(tmp < dp[idx][mask]) {
dp[idx][mask] = tmp;
next[idx][mask] = i;
}
}
}
return dp[idx][mask];
}
string construct(vector<string>& words, int start) {
int index = start;
string answer = words[index];
int state = 1 << index;
while(state != (1 << n) - 1) {
int nextIndex = next[index][state];
answer += words[nextIndex].substr(overlap[index][nextIndex]);
index = nextIndex;
state |= 1 << nextIndex;
}
return answer;
}
public:
string shortestSuperstring(vector<string>& words) {
init(words);
int minLength = INT_MAX;
int start = -1;
for(int i = 0; i < n; ++i) {
int cur = len[i] + solve(i, 1 << i);
if(minLength > cur) {
minLength = cur;
start = i;
}
}
return construct(words, start);
}
};
// 83 / 83 test cases passed.
// Status: Accepted
// Runtime: 348 ms
// Memory Usage: 49.2 MB
using raw array
int prefix(string &pre, string &post) {
int lPre = pre.length();
int lPost = post.length();
for(int len = min(lPre, lPost); len; --len) {
bool ok = true;
for(int i = 0; ok && i < len; ++i) {
ok = pre[lPre - len + i] == post[i];
}
if(ok) return len;
}
return 0;
}
class Solution {
int n;
int len[20] = {};
int overlap[20][20] = {};
int dp[20][1 << 12] = {};
int next[20][1 << 12];
void init(vector<string>& words) {
n = words.size();
memset(dp, -1, sizeof(dp));
for(int i = 0; i < n; ++i) {
len[i] = words[i].length();
}
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
if(i == j) continue;
overlap[i][j] = prefix(words[i], words[j]);
}
}
}
int solve(int idx, int mask) {
// cout << idx << ' '<< mask<<endl;
if(mask == (1 << n) - 1) return 0;
if(dp[idx][mask] != -1) return dp[idx][mask];
dp[idx][mask] = INT_MAX;
for(int i = 0; i < n; i++) {
if(!(mask & (1 << i))) {
int tmp = len[i] - overlap[idx][i] + solve(i, mask | (1 << i));
if(tmp < dp[idx][mask]) {
dp[idx][mask] = tmp;
next[idx][mask] = i;
}
}
}
return dp[idx][mask];
}
string construct(vector<string>& words, int start) {
int index = start;
string answer = words[index];
int state = 1 << index;
while(state != (1 << n) - 1) {
int nextIndex = next[index][state];
answer += words[nextIndex].substr(overlap[index][nextIndex]);
index = nextIndex;
state |= 1 << nextIndex;
}
return answer;
}
public:
string shortestSuperstring(vector<string>& words) {
init(words);
int minLength = INT_MAX;
int start = -1;
for(int i = 0; i < n; ++i) {
int cur = len[i] + solve(i, 1 << i);
if(minLength > cur) {
minLength = cur;
start = i;
}
}
return construct(words, start);
}
};
// 83 / 83 test cases passed.
// Status: Accepted
// Runtime: 24 ms
// Memory Usage: 8.7 MB