(ダブルシーケンス型動的計画法)lintcode難易度623・Kステップ編集

トピック

説明
小文字とターゲット文字列のみを含む文字列のセットを指定して、ターゲット文字列を取得するために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コードを分析します。

おすすめ

転載: blog.csdn.net/weixin_46035615/article/details/123870395