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 <= 121 <= words[i].length <= 20words[i]consists of lowercase English letters.- All the strings of
wordsare 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