classSolution{public:intlongestStrChain(vector<string>&words){constunordered_set<string>wordsSet{begin(words),end(words)};intans=0;for(conststring&word:words)ans=max(ans,longestStrChain(word,wordsSet));returnans;}private:// dp[s] := longest string chain where s is the last wordunordered_map<string,int>dp;intlongestStrChain(conststring&s,constunordered_set<string>&wordsSet){if(dp.count(s))returndp[s];intans=1;for(inti=0;i<s.length();++i){conststringpred=s.substr(0,i)+s.substr(i+1);if(wordsSet.count(pred))ans=max(ans,longestStrChain(pred,wordsSet)+1);}returndp[s]=ans;}};
classSolution{publicintlongestStrChain(String[]words){Set<String>wordsSet=newHashSet<>(Arrays.asList(words));intans=0;for(finalStringword:words)ans=Math.max(ans,longestStrChain(word,wordsSet));returnans;}// dp[s] := longest string chain where s is the last wordprivateMap<String,Integer>dp=newHashMap<>();privateintlongestStrChain(finalStrings,Set<String>wordsSet){if(dp.containsKey(s))returndp.get(s);intans=1;for(inti=0;i<s.length();++i){finalStringpred=s.substring(0,i)+s.substring(i+1);if(wordsSet.contains(pred))ans=Math.max(ans,longestStrChain(pred,wordsSet)+1);}dp.put(s,ans);returnans;}}
classSolution:deflongestStrChain(self,words:List[str])->int:wordsSet=set(words)# Dp(s) := longest chain where s is the last word@functools.lru_cache(None)defdp(s:str)->int:ans=1foriinrange(len(s)):pred=s[:i]+s[i+1:]ifpredinwordsSet:ans=max(ans,dp(pred)+1)returnansreturnmax(dp(word)forwordinwords)