一般來說這種求最長序列問題都可以用動態規劃來解決,那麼這道題也不例外。核心的思路是將用一長度的字符串都壓到同一個棧中,然後從最長的字符串開始往最短的逐級計算最長序列。還有一個地方關鍵點是判斷兩個字符串是否是有效的,即字符串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;
}
};