一般来说这种求最长序列问题都可以用动态规划来解决,那么这道题也不例外。核心的思路是将用一长度的字符串都压到同一个栈中,然后从最长的字符串开始往最短的逐级计算最长序列。还有一个地方关键点是判断两个字符串是否是有效的,即字符串w1和w2是否为长度差1,并且往w1中任意位置插入一个字符就可以得到w2.关键是找到状态转换方程,在这道题里面,我们用map<string,int> maxlen来记录以该字符串开头的序列的最长长度,状态转换方程为:
maxlen[w1]=max(maxlen[w1],maxlen[w2]+1);
class Solution {
public:
bool isvalid(const string &a,const string &b){
int idxa = 0,idxb = 0;
int alen =a.size(),blen=b.size();
int count =0;
while(idxa<alen&&idxb<blen){
if(a[idxa]!=b[idxb]){
count++;
idxb++;
}
else{
idxa++;
idxb++;
}
if(count>1)return false;
}
return true;
}
int longestStrChain(vector<string>& words) {
int res = 1;
map<int,vector<string>> mp;
for(int i=1;i<=16;i++)
mp[i]={};
map<string,int>maxlen;
for(auto w:words)
mp[w.size()].push_back(w);
int idx =16;
while(mp[idx].size()==0)idx--;
auto first = mp[idx];
int len1 =idx,len2=0;
vector<string> second;
for(auto w:first){
maxlen[w]=1;
}
while(idx){
idx--;
second = mp[idx];
if(second.size()==0){
first=second;
len1 = len2;
continue;
}
len2=idx;
for(auto w:second){
maxlen[w]=1;
}
if(len2==len1-1){
for(auto w1:second){
for(auto w2:first)
if(isvalid(w1,w2)){
maxlen[w1]=max(maxlen[w1],maxlen[w2]+1);
}
res = max(res,maxlen[w1]);
}
}
first = second;
len1 = len2;
}
return res;
}
};