記事のディレクトリ
1つのトピックの理解
入力:文字列配列words、文字列には小文字のみが含まれます
ルール:word1とword2の場合、word1の任意の位置に文字を追加してword2を取得すると、word1はword2の前身と呼ばれます。ワードチェーンは、単語のシーケンス[word_1、word_2、…、word_k]、k> = 1です。ここで、word_1はword_2の先行であり、word_2はword_3の先行です。
出力:単語から単語を選択して、単語チェーンの可能な限り長い長さである単語チェーンを形成します。
例1:
入力:words = [“ a”、“ b”、“ ba”、“ bca”、“ bda”、“ bdca”]
出力:4
説明:最も長い単語チェーンの1つは“ a”、“ ba 」、「bda」、「bdca」。
例2:
入力:words = [“ xbc”、“ pcxbcf”、“ xb”、“ cxbc”、“ pcxbc”]
出力:5
例2を読んだ後、5であるかわかりませんが、3である必要があると思います。この質問は、最長増加部分列に似ています。他の人の答えを読んだ後、単語から単語を選んでも、単語の連鎖を順番に形成する必要があるとは言えないことに気づきました。n個の単語を選択すると、元の配列の添え字に関係なく、任意の順序で単語チェーンを形成できます。
2動的計画法
問題解決の考え方は、最長増加部分列問題の考え方と同じです。
class Solution {
public int longestStrChain(String[] words) {
int n = words.length;
Arrays.sort(words, Comparator.comparingInt(String::length));
int[] dp = new int[n];
dp[0] = 1;
int max = 1;
for(int i=1;i<n;i++){
dp[i] = 1;
for(int j=0;j<i;j++){
if(isPredecessor(words[j],words[i])){
dp[i] = Math.max(dp[i],dp[j]+1);
}
}
max = Math.max(max,dp[i]);
}
return max;
}
private boolean isPredecessor(String word1,String word2){
if(word1.length()+1==word2.length()){
int dis = 0;
for(int i=0,j=0;i<word1.length() && j<word2.length();){
if(word1.charAt(i) == word2.charAt(j)){
j++;
i++;
}else{
j++;
dis++;
}
}
return dis<=1;
}
return false;
}
}
時間計算量O(n 2 ∗ l)O(n ^ 2 * l)O (n2∗l )。nは単語配列の長さ、lは各単語の長さです。