Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Find the Shortest Superstring in C++
Suppose we have an array A of strings, we have to find any smallest string that contains each string in A as a substring. We can also assume that no string in A is substring of another string in A.
So, if the input is like ["dbsh","dsbbhs","hdsb","ssdb","bshdbsd"], then the output will be "hdsbbhssdbshdbsd"
To solve this, we will follow these steps −
Define a function calc(), this will take a, b,
-
for initialize i := 0, when i < size of a, update (increase i by 1), do −
-
if substring of a from index i to end is at the start of b, then −
return size of b - size of a + i
-
return size of b
From main method, do these steps
ret := empty string
n := size of A
-
Define one 2D array graph of size n x n −
-
for initialize j := 0, when j < n, update (increase j by 1), do −
graph[i, j] := calc(A[i], A[j])
graph[j, i] := calc(A[j], A[i])
-
Define an array dp of size: 2^n x n.
Define an array path of size: 2^n x n.
minVal := inf
last := -1
-
for initialize i := 0, when i < 2^n, update (increase i by 1), do −
-
for initialize j := 0, when j < n, update (increase j by 1), do −
dp[i, j] := inf
-
-
for initialize i := 0, when i < 2^n, update (increase i by 1), do −
-
for initialize j := 0, when j < n, update (increase j by 1), do −
-
if i AND 2^j is non-zero, then
prev := i ^ (2^j)
-
if prev is same as 0, then −
dp[i, j] := size of A[j]
-
Otherwise
-
for initialize k := 0, when k < n, update (increase k by 1), do −
-
if prev AND 2^k and df[prev,k] is not inf and df[prev,k] + graph[k,j] < dp[i,j], then
dp[i, j] := dp[prev, k] + graph[k, j]
path[i, j] := k
-
-
-
-
if i is same as 2^n - 1 and dp[i, j] < minVal, then −
minVal := dp[i, j]
last := j
-
curr := 2^n - 1
Define one stack st
-
while curr > 0, do −
insert last into st
temp := curr
curr := curr - (2^last)
last := path[temp, last]
i := top element of st
delete element from st
ret := ret + A[i]
-
while (not st is empty), do −
j := top element of st
delete element from st
ret := ret concatenate substring of A[j] from (size of A[j] - graph[i,j] to end)
i := j
return ret
Let us see the following implementation to get better understanding −
Example
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int calc(string& a, string& b){
for (int i = 0; i < a.size(); i++) {
if (b.find(a.substr(i)) == 0) {
return b.size() - a.size() + i;
}
}
return (int)b.size();
}
string shortestSuperstring(vector<string>& A){
string ret = "";
int n = A.size();
vector<vector<int> > graph(n, vector<int>(n));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
graph[i][j] = calc(A[i], A[j]);
graph[j][i] = calc(A[j], A[i]);
}
}
int dp[1 << n][n];
int path[1 << n][n];
int minVal = INT_MAX;
int last = -1;
for (int i = 0; i < (1 << n); i++)
for (int j = 0; j < n; j++)
dp[i][j] = INT_MAX;
for (int i = 1; i < (1 << n); i++) {
for (int j = 0; j < n; j++) {
if ((i & (1 << j))) {
int prev = i ^ (1 << j);
if (prev == 0) {
dp[i][j] = A[j].size();
} else {
for (int k = 0; k < n; k++) {
if ((prev & (1 << k)) && dp[prev][k] !=
INT_MAX && dp[prev][k] + graph[k][j] < dp[i][j]) {
dp[i][j] = dp[prev][k] + graph[k][j];
path[i][j] = k;
}
}
}
}
if (i == (1 << n) - 1 && dp[i][j] < minVal) {
minVal = dp[i][j];
last = j;
}
}
}
int curr = (1 << n) - 1;
stack<int> st;
while (curr > 0) {
st.push(last);
int temp = curr;
curr -= (1 << last);
last = path[temp][last];
}
int i = st.top();
st.pop();
ret += A[i];
while (!st.empty()) {
int j = st.top();
st.pop();
ret += (A[j].substr(A[j].size() - graph[i][j]));
i = j;
}
return ret;
}
};
main(){
Solution ob;
vector<string> v = {"dbsh","dsbbhs","hdsb","ssdb","bshdbsd"};
cout << (ob.shortestSuperstring(v));
}
Input
{"dbsh","dsbbhs","hdsb","ssdb","bshdbsd"}
Output
hdsbbhssdbshdbsd