使用動態規劃求解字串問題
72. Edit Distance--字串編輯問題
問題描述:
Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)You have the following 3 operations permitted on a word:
a) Insert a character
b) Delete a character
c) Replace a character
問題解析:
1. 本題是求兩個字串s1和s2,編輯s1讓其變為s2。可以在s1中插入字元操作、刪除字元操作、替換字元操作,每次操作增加步驟1次,求s1變為s2的最小步驟數。
2. 解決此類問題經典解法就是用動態規劃。
(1)s1大小為size1,s2大小為size2。定義一個size1+1*size2+1的dp,其中dp[i][j]表示s1的前i的字元變為和s2的前j個字元所需要的最小步驟數。
(2)dp[i][j]的值應該是:當s1[i]==s2[j]時,dp[i][j]==dp[i-1][j-1];當s[i] != s[j]時,dp[i][j] = dp[i-1][j]+1(刪除一個字元)、dp[i][j] = dp[i][j-1] + 1(新增一個字元)、dp[i][j] = dp[i-1][j-1] + 1(替換一個字元)。選擇三者步驟數最少的一個。
程式碼如下:
class Solution { public: // 使用動態規劃來解決此問題,建立dp,dp[i][j]表示word1的i個字元轉化為word2的前j個字元所需要的花費 int minDistance(string word1, string word2) { int m = (int)word1.size(); int n = (int)word2.size(); // 建立dp vector<vector<int>>dp(m+1, vector<int>(n+1, 0)); // 初始化第一行,代表word1為空時轉化為word2 for(int j=1; j<=n; ++j) dp[0][j] = dp[0][j-1] + 1; // 初始化第一列,代表word2為空時轉化為word1 for(int i=1; i<=m; ++i) dp[i][0] = dp[i-1][0] + 1; for(int i=1; i<=m; ++i) { for(int j=1; j<=n; ++j) { // dp[i-1][j]表示word1前i-1轉換為word2前j個,需要花費,刪掉1個就是前i和前j // dp[i][j-1]表示word1前i轉換為word2前j-1個,需要花費,新增1個就是前i和前j // dp[i-1][j-1]表示word1前i-1轉換為word2前j-1個需要花費。word1[i]==word2[j],則不需要花費就是前i和前j.否則需要替換多花費1 int z; dp[i][j] = dp[i-1][j] < dp[i][j-1] ? dp[i-1][j]+1 : dp[i][j-1]+1; z = (word1[i-1] == word2[j-1] ? dp[i-1][j-1] : dp[i-1][j-1]+1); dp[i][j] = dp[i][j] < z ? dp[i][j] : z; } } return dp[m][n]; } };
115. Distinct Subsequences---求字串S中有幾個字串t
問題描述:
Given a string S and a string T, count the number of distinct subsequences of S which equals T.
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining
characters. (ie, "ACE"
is a subsequence of "ABCDE"
while "AEC"
is
not).
Here is an example:
S = "rabbbit"
, T = "rabbit"
Return 3
.
問題解析:
1. 此題是求一個字串S中有幾個字串t。可以轉化為上題,只是通過在字串S中刪除字元來變為字串t,看有幾種解法。
2. 解決此類問題經典解法就是用動態規劃。
(1)s大小為size1,t大小為size2。定義一個size1*size2的dp,其中dp[i][j]表示s1的前i+1的字元變為和s2的前j+1個字元的方法數。
(2)dp[i][j]的值應該是:當s1[i]==s2[j]時,dp[i][j]==dp[i-1][j] + dp[i-1][j-1],表示的是使用當前這個字元和不要s中當前這個字元總共方法數;當s[i] != s[j]時,dp[i][j] = dp[i-1][j],s中當前這個字元一定用不上,所以表示不用當前這個字元的方法數。
程式碼如下:
class Solution {
public:
// 利用動態規劃來做
int numDistinct(string s, string t)
{
if(s.empty())
return 0;
if(t.empty())
return 1;
int ssize = s.size();
int tsize = t.size();
vector<vector<int>> dp(ssize, vector<int>(tsize, 0));
// 填寫第一行
if(s[0] ==t[0])
dp[0][0]=1;
// 填寫第一列
for(int i=1; i<ssize; ++i)
{
if(t[0] ==s[i])
dp[i][0] = 1+ dp[i-1][0];
else
dp[i][0] = dp[i-1][0];
}
// 填寫剩餘的dp
for(int i=1; i<ssize; ++i)
{
for(int j=1; j<tsize; ++j)
{
if(s[i] == t[j])
dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
else
dp[i][j] = dp[i-1][j];
}
}
return dp[ssize-1][tsize-1];
}
};
115. Distinct
Subsequences
相關推薦
使用動態規劃求解字串問題
72. Edit Distance--字串編輯問題 問題描述: Given two words word1 and word2, find the minimum number of steps
動態規劃求解-將字串A變換為字串B 所用的最少字元操作次數
問題描述: 設A 和B 是2 個字串。要用最少的字元操作將字串A 轉換為字串B。 這裡所說的字元操作包括 (1)刪除一個字元; (2)插入一個字元; (3)將一個字元改為另一個字元。 將字串
動態規劃求解兩個字串的最大公共子串問題
最大公共子串長度問題就是:求兩個串的所有子串中能夠匹配上的最大長度是多少。比如:"abcdkkk" 和 "baabcdadabc",可以找到的最長的公共子串是"abcd",所以最大公共子串長度為4。下面的程式是採用矩陣法進行求解的,這對串的規模不大的情況還是比較有效的解法。請
練習題7:袋鼠過河(使用了動態規劃求解)
odin tdi font n+1 解法 append 動態規劃 split() 需要 題目描述 一只袋鼠要從河這邊跳到河對岸,河很寬,但是河中間打了很多樁子,每隔一米就有一個,每個樁子上都有一個彈簧,袋鼠跳到彈簧上就可以跳的更遠。每個彈簧力量不同,用一個數字代表它的力量
動態規劃 求解 Minimum Edit Distance
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
P2679 [NOIP2015]子串-動態規劃,字串
有兩個僅包含小寫英文字母的字串 AA 和 BB。 現在要從字串 A 中取出 k 個互不重疊的非空子串,然後把這 k 個子串按照其在字串 A 中出現的順序依次連線起來得到一個新的字串。請問有多少種方案
01揹包問題(動態規劃求解)
這兩天c++的習題開始不考察c++了,開始考察動態規劃問題,唉,沒學過動態規劃演算法來編這題目真是一把辛酸淚,下面給出題目(題目來源:郭瑋老師的mooc) 2:Charm Bracelet 檢視 提交 統計 提問 總時間限制: 1000ms 記憶體限制: 655
動態規劃求解(添+號求最小值和問題)
案例提出:在一個n位整數a(只考慮正整數的情況)中插入r個加號,將它分成r+1個整數,找出一種加號的插入方法,使得這r+1個整數的和最小。 動態規劃設計要點:對於一般插入r個+號問題,採用列舉不適合。注意到插入r個+號是一個多階層決策問題,所以採用動態規劃 來求解是最適宜的
動態規劃求解最長上升子序列問題
// ch12.cpp: 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include "iostream" #include "vector" using namespace std; int main() { //輸入資料 int N
動態規劃求解最長公共子序列的C++演算法實現
#include<iostream> using namespace std; int CommonOrder(char x[] ,int m ,char y[], int n, char z[]) { int i,j,k; int L[10][1
使用動態規劃求解旅行商問題
旅行商問題是np問題,在集合表示那裡用set去實現效率很很低,而且要儲存的數都是不重複的比較小的整數,所以這裡用二進位制串表示集合。比如集合{1,3,5,6,7}表示成二進位制串用1110101,其中集合裡面有的數對應的位數寫成1,沒有的寫成0。要判斷第3位是不是1,就把 1110101右移(3-1)位,
動態規劃求解01揹包問題-買糖果(京東實習筆試題)
網址連結 思路 之前想的是如果使用揹包問題求解,則問題的空間複雜度很大,這個只包含1和2兩種體積的方法,因此可以適當簡化。 我看了別人提交的答案,直接使用dp,提交了也可以AC。。 程式碼 #include <cstdlib> #in
揹包問題,動態規劃求解,matlab程式碼,c++程式碼
最近寫論文接觸到揹包問題,查閱網上一些資料,對於簡單的揹包問題,動態規劃演算法可以求解,最近花時間整理整理。 揹包問題描述: 有編號分別為a,b,c,d,e 的五件物品,它們的重量分別是 2,2,6,5,4,它們的價值分別是 6,3,5,4,6,現在給你個承重為 10 的
硬幣找零問題(動態規劃求解)
如果我們有面值為1元、3元和5元的硬幣若干枚,如何用最少的硬幣湊夠11元? (表面上這道題可以用貪心演算法,但貪心演算法無法保證可以求出解,比如1元換成2元的時候) 首先我們思考一個問題,如何用最少的硬幣湊夠i元(i<11)?為什麼要這麼問呢? 兩個原因:1.當
動態規劃求解硬幣找零問題——Java實現
動態規劃的基本思想是將待求解問題分解成若干個子問題,先求解子問題,並將這些子問題的解儲存起來,如果以後在求解較大子問題的時候需要用到這些子問題的解,就可以直接取出這些已經計算過的解而免去重複運算。儲存子問題的解可以使用填表方式,例如儲存在陣列中。 動態規劃的主要難點在於
動態規劃求解國際象棋中車點到點的最短路徑總數
題目:國際象棋中的車可以水平或豎直移動。一個車從棋盤的一角(0,0)移動到另一角(n,n),有多少種最短路徑。 分析:對於n*n的棋盤,從(0,0)移動到(n,n)的最短路徑總數應該為C(2n, n), 因為必走2n步,其中n步向左,剩下為向右。 public clas
類動態規劃求解較小規模的最大團問題(Python實現)
1.圖:由點、邊(點與點之間連線),組成的集合,如點集V=[0,1,2,3,4],邊集E=[[1,3,4],[2,3,4],[4],[4],[]],則(V,E)就是一個圖,其表達的意思如下: 該圖中含有5個端點,分別為0,1,2,3,4,這些點存在V中,如端點1對應V
動態規劃求解最長公共子序列(LCS)
看了《演算法導論》中文第二版P208的動態規劃求解LCS問題,覺得很贊,但總覺得算導寫得有些晦澀,希望自己能寫得簡單易懂一些,純當鍛鍊了,歡迎指導交流。 首先,子序列和子串是不一樣的。子串是連續的,而子序列中的元素組成可以是不連續的,但元素的位置下標
動態規劃求解編輯距離問題
題目描述: 要求兩字串有差異的字元個數。例如: aaaaabaaaaa aaaaacaabaa 這兩個字串,最大公共字串長度是5,但它們只有兩個字元不同,函式輸出值應為2。 如果是: aaabbbcccddd aaaeeeddd 函式的輸出值應該是6。 比較形象地形容一下,把
[Qt][Floyd演算法] 動態規劃求解最短行駛路徑 原始碼及演示程式
首先給出程式下載連結: [問題描述] 給定一個的矩形網格,設其左上角為起點S。一輛汽車從起點S出發駛向右下角終點T。網格邊上的數字表示距離。在若干網格點處設定了障礙,表示該網格點不可到達。試設計一個