トピック
説明
小文字とターゲット文字列のみを含む文字列のセットを指定して、ターゲット文字列を取得するためにk回以内に操作できるすべての文字列を出力します。
文字列に対して次の3つの操作を実行できます。
1文字追加
1文字削除
1文字を置き換えます
サンプル
例1:
与えられた文字列["abc","abd","abcd","adc"]
、ターゲット文字列は"ac"
、k = 1
return["abc","adc"]
入力:
["abc"、 "abd"、 "abcd"、 "adc"]
"ac"
1
出力:
["abc"、 "adc"]
説明:
" abc"は"b"を削除
します"adc"は"d"を削除します
例2:
入力:
["acc"、 "abcd"、 "ade"、 "abbcd"]
"abc"
2
出力:
["acc"、 "abcd"、 "ade"、 "abbcd"]
説明:
"acc" 「c」を「b」に変更
「abcd」ドロップ「d」
「ade」「d」を「b」に変更「e」を「c」に変更
「abbcd」ドロップ「b」と「d」
分析する
このような問題に遭遇したとき、この問題にn個の文字列が与えられたことを除けば、以前の2つのシーケンスの動的計画法とほぼ同じだと思いました。前回と同じ方法を使用しましたが、ループがもう1つあります。各文字列とターゲット文字列、動的計画法の問題は同じです。最初に最後のステップを分析し、次に遷移方程式を分析します。
最後のステップ
実行できる操作には、置換、削除、追加などがあり
ます。置換する場合は、最後の文字をターゲット文字に置き換え、ターゲットの最初のn-1項目と現在の文字列の最初のn-1項目を確認します。
ターゲットの最初のn個のアイテムと現在の文字列の最初のn-1個のアイテムを確認します。追加
するときは、ターゲット文字列の最初のn-1個のアイテムと最初のn-1個のアイテムを確認します。現在の文字列の項目が
最後の2つの文字列になります。同じ場合は、2つの文字列の最初のn-1項目に到達するだけで済みます。
合計で4つのケースがあり、必要な最小ステップを選択して比較します。 k以下の場合、この文字列が回答に追加されます。
伝達方程式
ステータスf[i][j] iは現在の文字列の長さを表し、jはターゲット文字列の長さを表します。f[i] [j] = min(f [i-1] [j] +1 delete、f [i]] [j-1] +1増加、f [i-1] [j-1] +1置換、f [i-1] [j-1] |最後の文字は同じ)
コードセクション
1.初期化
状態は、文字列が空の場合を初期化し、このときの値は、abcや空の文字列などの別の文字列の長さに等しいため、少なくとも3つのステップが必要です。
int strlen=str.size();
int targetlen=target.size();
vector<vector<int> > f(strlen+1,vector<int>(targetlen+1));
f[0][0]=0; //初始化
for(int i=1;i<=targetlen;i++) //一个为空一个不为空
f[0][i]=i;
for(int i=1;i<=strlen;i++)
f[i][0]=i;
2.ダイナミックゲージコア
最初の3つのケースでは、最初に最小値を比較して選択し、最後の文字が等しいかどうかを判断してから、最後のケースを比較します
for(int i=1;i<=strlen;i++) //动规核心
{
for(int j=1;j<=targetlen;j++)
{
f[i][j]=min(f[i-1][j],f[i][j-1])+1; //增删
f[i][j]=min(f[i][j],f[i-1][j-1]+1); //替换
if(str[i-1]==target[j-1]) //相同时
f[i][j]=min(f[i][j],f[i-1][j-1]);
}
}
return f[strlen][targetlen];
3.ループ呼び出しは、各文字列が要件を満たしているかどうかを計算します
一致する文字列を回答に保存します
int wordlen=words.size();
vector<string> ans;
for(int i=0;i<wordlen;i++)
{
if(mincnt(words[i],target)<=k)
ans.push_back(words[i]);
}
return ans;
完全なコード
class Solution {
public:
int mincnt(string str,string target)
{
int strlen=str.size();
int targetlen=target.size();
vector<vector<int> > f(strlen+1,vector<int>(targetlen+1));
f[0][0]=0; //初始化
for(int i=1;i<=targetlen;i++) //一个为空一个不为空
f[0][i]=i;
for(int i=1;i<=strlen;i++)
f[i][0]=i;
for(int i=1;i<=strlen;i++) //动规核心
{
for(int j=1;j<=targetlen;j++)
{
f[i][j]=min(f[i-1][j],f[i][j-1])+1; //增删
f[i][j]=min(f[i][j],f[i-1][j-1]+1); //替换
if(str[i-1]==target[j-1]) //相同时
f[i][j]=min(f[i][j],f[i-1][j-1]);
}
}
return f[strlen][targetlen];
}
vector<string> kDistance(vector<string> &words, string &target, int k) {
int wordlen=words.size();
vector<string> ans;
for(int i=0;i<wordlen;i++)
{
if(mincnt(words[i],target)<=k)
ans.push_back(words[i]);
}
return ans;
}
};
要約する
現在の方法は、テストサンプルの80%しか合格していません。次の記事では、繰り返しとACコードを分析します。