[AlgoExpert] Longest String Chain

Longest String Chain

  • Time : O(n len(s) n * n)
  • Space : O(n)

  • compare two string with length diff is 1 will take len(s) * n * n in worst case.

  • worst case is there are only two group of string [len(s), len(s) - 1] and number of two groups’s difference is at most one.
  • In this case, time complexity will make O(len(s) * (n / 2) * (n / 2))
  • Length of TC distribution is wide, time complexity will converge to O(n * len(s) * n)
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
bool adj(string& origin, string& target) {
int i = 0, j = 0, diff = 0;
while(i < origin.size() and j < target.size() and diff < 2) {
if(origin[i] == target[j]) {
i++; j++;
} else {
i++; diff++;
}
}
return diff <= 1;
}

int helper(vector<string>& A, int p, vector<int>& dp, vector<int>& path, unordered_map<int, vector<int>>& mp) {
if(dp[p] != -1) return dp[p];
dp[p] = 0;
for(auto& nxt : mp[A[p].length() - 1]) {
if(adj(A[p], A[nxt])) {
helper(A, nxt, dp, path, mp);
if(dp[nxt] + 1 > dp[p]) {
dp[p] = dp[nxt] + 1;
path[p] = nxt;
}
}
}
return dp[p];
}

vector<string> longestStringChain(vector<string> A) {
int n = A.size(), ma = 0, p = -1;
unordered_map<int, vector<int>> mp;
vector<int> dp(n, -1);
vector<int> path(n, -1);

for(int i = 0; i < n; i++)
mp[A[i].length()].push_back(i);

for(int i = 0; i < n; i++) {
if(dp[i] == -1)
helper(A, i, dp, path, mp);
if(ma < dp[i]) {
ma = dp[i];
p = i;
}
}

vector<string> res;
while(p != -1) {
res.push_back(A[p]);
p = path[p];
}

return res;
}
  • Time : O(n len(s) len(s))
  • Space : O(n)

  • making smaller string will take len(s) * len(s)

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

vector<string> smaller(string& s) {
vector<string> res;
for(int i = 0; i < s.length(); i++) {
res.push_back(s.substr(0,i) + s.substr(i+1));
}
return res;
}

int helper(vector<string>& A, int p, vector<int>& dp, vector<int>& path, unordered_map<string, int>& mp) {
if(dp[p] != -1) return dp[p];
dp[p] = 0;
for(auto& nxt : smaller(A[p])) {
if(mp.count(nxt)) {
helper(A, mp[nxt], dp, path, mp);
if(dp[mp[nxt]] + 1 > dp[p]) {
dp[p] = dp[mp[nxt]] + 1;
path[p] = mp[nxt];
}
}
}
return dp[p];
}

vector<string> longestStringChain(vector<string> A) {
int n = A.size(), ma = 0, p = -1;
unordered_map<string, int> mp;
vector<int> dp(n, -1);
vector<int> path(n, -1);

for(int i = 0; i < n; i++)
mp[A[i]] = i;

for(int i = 0; i < n; i++) {
if(dp[i] == -1)
helper(A, i, dp, path, mp);
if(ma < dp[i]) {
ma = dp[i];
p = i;
}
}

vector<string> res;
while(p != -1) {
res.push_back(A[p]);
p = path[p];
}

return res;
}
Author: Song Hayoung
Link: https://songhayoung.github.io/2022/05/08/PS/AlgoExpert/longest-string-chain/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.