-
Notifications
You must be signed in to change notification settings - Fork 119
/
Copy pathFind the Shortest Superstring.cpp
114 lines (102 loc) · 2.62 KB
/
Find the Shortest Superstring.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
vector<vector<int> > dp,pre,par;
bool startWith(string s, string t)
{
// returns true if string s starts with string t
int i;
for(i=0; i<s.length()&&i<t.length(); i++)
{
if(s[i]==t[i])
continue;
else
return false;
}
if(i==t.length())
return true;
else
return false;
}
int calc(string A, string B)
{
// calculate the number of extra characters required to be appended to A
// if A is followed by B
// for eg. calc("abcd","cdef") = 2
int a=A.length(),b=B.length();
for(int i=0; i<a; i++)
{
if(a-i<=b&&startWith(B,A.substr(i)))
{
return b-(a-i);
}
}
return b;
}
int finalMask,n;
int helper(int mask, int last)
{
// returns the minimum length of string required if last string appended was A[last]
// the sets bit in mask represents the strings that were already appended to the final string
if(mask==finalMask) // all strings are appended in final string
return 0;
if(dp[mask][last]!=-1) // memoization
return dp[mask][last];
int mn=INT_MAX;
int p;
for(int i=0; i<n; i++)
{
if(mask&(1<<i))
continue;
int cost=pre[last][i]+helper(mask|(1<<i),i); // extra characters need to be appended
if(cost<mn)
{
mn=cost;
p=i;
}
}
par[mask][last]=p; // store parent, so that it is easy to traceback and find the final result
return dp[mask][last]=mn; // store result in DP table
}
class Solution {
public:
string shortestSuperstring(vector<string>& A) {
n=A.size();
pre.assign(n,vector<int>(n)); // for pre-computing calc(a,b) for all pairs of strings
par.assign(1<<n,vector<int>(n,-1));
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
if(j==i)
continue;
pre[i][j]=calc(A[i],A[j]);
}
}
finalMask=(1<<n)-1;
dp.assign(1<<n,vector<int>(n,-1));
int len=INT_MAX; // len will contain minimum length of required string
int ind;
for(int i=0; i<n; i++)
{
int prev=len;
len=min(len, (int)A[i].length()+helper(1<<i,i));
if(len!=prev)
{
ind=i;
}
}
// Now traceback to find the final answer
string ans=A[ind];
int msk=1<<ind;
int prev_ind=ind;
ind=par[msk][ind];
while(ind!=-1)
{
len=pre[prev_ind][ind];
int alen=A[ind].length();
ans+=A[ind].substr(alen-len,len);
msk=msk^(1<<ind);
prev_ind=ind;
ind=par[msk][ind];
}
return ans;
}
};