LeetCode Solutions
1048. Longest String Chain
Time: $O(n\max(|\texttt{words[i]}|)^2)$ Space: $O(n)$
class Solution {
public:
int longestStrChain(vector<string>& words) {
const unordered_set<string> wordsSet{begin(words), end(words)};
int ans = 0;
for (const string& word : words)
ans = max(ans, longestStrChain(word, wordsSet));
return ans;
}
private:
// dp[s] := longest string chain where s is the last word
unordered_map<string, int> dp;
int longestStrChain(const string& s, const unordered_set<string>& wordsSet) {
if (dp.count(s))
return dp[s];
int ans = 1;
for (int i = 0; i < s.length(); ++i) {
const string pred = s.substr(0, i) + s.substr(i + 1);
if (wordsSet.count(pred))
ans = max(ans, longestStrChain(pred, wordsSet) + 1);
}
return dp[s] = ans;
}
};
class Solution {
public int longestStrChain(String[] words) {
Set<String> wordsSet = new HashSet<>(Arrays.asList(words));
int ans = 0;
for (final String word : words)
ans = Math.max(ans, longestStrChain(word, wordsSet));
return ans;
}
// dp[s] := longest string chain where s is the last word
private Map<String, Integer> dp = new HashMap<>();
private int longestStrChain(final String s, Set<String> wordsSet) {
if (dp.containsKey(s))
return dp.get(s);
int ans = 1;
for (int i = 0; i < s.length(); ++i) {
final String pred = s.substring(0, i) + s.substring(i + 1);
if (wordsSet.contains(pred))
ans = Math.max(ans, longestStrChain(pred, wordsSet) + 1);
}
dp.put(s, ans);
return ans;
}
}
class Solution:
def longestStrChain(self, words: List[str]) -> int:
wordsSet = set(words)
# Dp(s) := longest chain where s is the last word
@functools.lru_cache(None)
def dp(s: str) -> int:
ans = 1
for i in range(len(s)):
pred = s[:i] + s[i + 1:]
if pred in wordsSet:
ans = max(ans, dp(pred) + 1)
return ans
return max(dp(word) for word in words)