1. 程式人生 > >動態規劃之編輯距離

動態規劃之編輯距離

1、問題

例如兩個字串 FAMILY 和 FRAME ,有兩種

對齊方式:

1)、

F_A MIL Y

FRAME

2)、

_FAMILY

FRAME

第 1 種對齊需要付出的代價: 4 ,插入 R ,將 I 替換為 E ,刪除 L 、 Y 。
第 2 種對齊需要付出的代價: 5 ,插入 F,將 F 替換為 R ,將 I 替換為 E ,刪除 L 、 Y 。
編輯距離是指將一個字串變換為另一個字串所需要的最小編輯操作。

怎麼找到兩個字串 x [1 ,...,m ] 和 y [1 ,...,n ] 的編輯距離

2、分析

假設已經知道 d [ i ][ j ] 是 X i ={ x 1 ,x 2 ,x 3 ,...,x i } 和 Y j ={ y 1 ,y 2 ,y 3 ,...,y j } 的編輯距離,分3種情況

1)

x1,  x2,  x3,  x4, x(i - 1),  x(i)

y1,  y2,  y3, y4, y(j - 1),  _

推出

d [ i ][ j ]= d [ i −1][ j ]+1

2)

x1,  x2,  x3,  x4, x(i - 1),  x(i)

y1,  y2,  y3, y4, y(j - 1),  _

推出

d [ i ][ j ]= d [ i ][ j −1]+1

3)

x1,  x2,  x3,  x4, x(i - 1),  x(i)

y1,  y2,  y3, y4, y(j - 1),  y(j)

如果x(i) == y(j)推出d [ i ][ j ]= d [ i - 1 ][ j −1] +0,這裡假設diff(i, j) = 0

否則推出d [ i ][ j ]= d [ i - 1 ][ j −1] + 1,這裡假設diff(i, j) = 1

所以

d [ i ][ j ] = min{ d [ i − 1][ j ] + 1, d [ i ][ j − 1] + 1, d [ i − 1][ j − 1] + diff ( i , j )}

然後我們構建一個二維陣列,初始化第一行和第一列按序號增大,為什麼是按照序號增大,比如i=1,j等於1的時候,我們需要操作一步,如果j=2的時候,我們需要操作2步,以此類推,而不是都賦值為0,如下圖


3、程式碼實現

#include <iostream>
#include <cstring>

using namespace std;

#define LEN 1024

char s1[LEN], s2[LEN];
int data[LEN][LEN];

//比較大小的函式
int min(int a, int b)
{
	return a > b ? b : a;	
}

//求最小編輯的函式
int editDistance(char *s1, char *s2, int len1, int len2)
{
	for (int i = 1; i <= len1; ++i)
	{
		for (int j = 1; j <= len2; ++j) 
		{
			int temp = min(data[i][j - 1] + 1, data[i - 1][j] + 1);
			//這裡不是data[i - 1][j - 1] == data[j][j];
			if (s1[i] == s2[j])
			{
				//這裡不是temp = min(temp, data[i - 1][j - 1]);
				data[i][j] = min(temp, data[i - 1][j - 1]);
			}
			else 
			{
				//這裡不是temp = min(temp, data[i - 1][j - 1] + 1);
				data[i][j] = min(temp, data[i - 1][j - 1] + 1);
			}
		}
	}
	return data[len1][len2];
}


int main()
{
	std::cout << "請輸入2個字串" << std::endl;
	std::cin >> s1;
	std::cin >> s2;
	int len1 = strlen(s1);
	int len2 = strlen(s2);
	//初始化第一列
	for (int i = 0; i <= len1; ++i) 
	{
		data[i][0] = i;	
	}
	//初始化第一行
	for (int j = 0; j <= len2; ++j)
	{
		data[0][j] = j;	
	}
	int editDis = editDistance(s1, s2, len1, len2);
	std::cout << "最小的編輯距離是" << editDis << std::endl;
	return 0;	
}

4、執行結果

請輸入2個字串
family
frame
最小的編輯距離是4


5、總結

一般求最少的問題,最長的問題,我們一般看到最的問題就要想到動態規劃,然後找到遞推關係式

d [ i ][ j ] = min{ d [ i − 1][ j ] + 1, d [ i ][ j − 1] + 1, d [ i − 1][ j − 1] + diff ( i , j )}

這裡的時間複雜度和空間複雜度都是O(n* m),n是字串1的長度,m是字串2的長度。

相關推薦

動態規劃編輯距離問題

由公式可以看出,(i-1,j)對應刪除操作,(i,j-1)對應插入操作。 可以這樣理解,現在耗費了di-1,j步操作將字串a(1,i-1)轉換成了b(1,j),則在將a(1,i)轉換成b(1,j)時,我們可以直接刪掉字元a(i), 問題變成a(1,i-1)轉換成b(1,j),從而dij就等於d

動態規劃編輯距離:用最少的字元操作將A變換成B

一、問題描述                 設A和B是兩個字串,長度分別為n,m要用最少的字元操作(包括字元的插入、刪除、修改),這樣的操作稱為字串A到B的操作距離,記為d(A,B)。 二、思路分析                 把求解編輯距離分為字串A從0個字元逐漸增

動態規劃編輯距離

1、問題例如兩個字串 FAMILY 和 FRAME ,有兩種對齊方式:1)、F_A MIL YFRAME2)、_FAMILYFRAME第 1 種對齊需要付出的代價: 4 ,插入 R ,將 I 替換為 E ,刪除 L 、 Y 。第 2 種對齊需要付出的代價: 5 ,插入 F,將

動態規劃-LeetCode72-編輯距離

題目 給定兩個單詞 word1 和 word2,計算出將 word1 轉換成 word2 所使用的最少運算元 。 你可以對一個單詞進行如下三種操作: 插入一個字元 刪除一個字元 替換一個字元 示例 1: 輸入: word1 = "horse", word2 = "ros" 輸出: 3 解釋

動態規劃求解編輯距離問題

題目描述: 要求兩字串有差異的字元個數。例如: aaaaabaaaaa aaaaacaabaa 這兩個字串,最大公共字串長度是5,但它們只有兩個字元不同,函式輸出值應為2。 如果是: aaabbbcccddd aaaeeeddd 函式的輸出值應該是6。 比較形象地形容一下,把

【1】【leetcode-72 動態規劃編輯距離

ade 均可 distance 刪除 new ret min sta 插入 (沒思路,很典型,重要) 給定兩個單詞 word1 和 word2,計算出將 word1 轉換成 word2 所使用的最少操作數 。 你可以對一個單詞進行如下三種操作: 插入一個字符 刪

[C++] 動態規劃矩陣連乘、最長公共子序列、最大子段和、最長單調遞增子序列

每次 種子 () return 避免 amp 可能 text com 一、動態規劃的基本思想   動態規劃算法通常用於求解具有某種最優性質的問題。在這類問題中,可能會有許多可行解。每一個解都對應於一個值,我們希望找到具有最優值的解。   將待求解問題分解成若幹個子問題,先求

動態規劃01背包問題(含代碼C)

bsp sys 最優解 ret 時間復雜度 維數 style 時間 沒有 1.動態規劃的基本思想   動態規劃算法通常用於求解具有某種最優性質的問題。其基本思想也是將待求解問題分解成若幹個子問題,先求解子問題,然後從這些子問題的解得到原問題的解。與分治法不同的是,適合於用動

LeetCode-動態規劃Triangle

pre family add where throw to do 16px owin ext 題目描述 Given a triangle, find the minimum path sum from top to bottom. Each step you may mo

動態規劃01背包詳解

題解 for 可見 round 往裏面 原創 ble -a eight 先看問題: 有N件物品和一個容量為V的背包。(每種物品均只有一件)第i件物品的費用是c[i],價值是w[i]。求解將哪些物品裝入背包可使價值總和最大。 通過閱讀問題,因為背包就是要往裏面放東西,所以一件

動態規劃完全背包詳解

現在 max 相同 維數 自己 一維數組 方法 table 得到 在昨天我已經很詳細的講解過01背包的動態規劃問題了,今天我講解的是完全背包的問題,這是01背包的詳解:http://www.cnblogs.com/Kalix/p/7617856.html 先看問題:在n種物

動態規劃遞推求解

com 輸出 b站 eof sea 註意 des 不難 sca 動態規劃在B站上有個up主講得不錯,在此分享出來,如果對動態規劃還比較懵逼的可以先去看看。 https://www.bilibili.com/video/av16544031/?from=sea

動態規劃最長遞增子序列(LIS)

lib sca while -c -o 組成 describe log ret 在一個已知的序列{ a1,a2,……am}中,取出若幹數組成新的序列{ ai1, ai2,…… aim},其中下標 i1,i2, ……im保持遞增,即新數列中的各個數之間依舊保持原

動態規劃最長公共子序列(LCS)

int tdi -s can 數組下標 include har 遞推 最長公共子序列 在字符串S中按照其先後順序依次取出若幹個字符,並講它們排列成一個新的字符串,這個字符串就被稱為原字符串的子串 有兩個字符串S1和S2,求一個最長公共子串

動態規劃背包問題實現php

動態規劃 背包問題php 最近在研究動態規劃算法,剛好看到背包問題。看到網上講解這方面問題很多,感覺都有點不明白,後面細思苦想好久,終於理解這個思路。於是寫下個人見解以及解題思路。背包問題描述如下:有編號分別為a,b,c,d,e的五件物品,它們的重量分別是4,2,6,5,3,它們的價值分別是6,3,5

動態規劃最長公共子序列

圖片 輔助 length ret %s csp TP 子序列 輸出 原理請參考《算法導論》 定義常量 enum {upper_left, up, left}; #define LENGTHA (sizeof(A)/sizeof(A[0])) #define LENGTHB

POJ1742 coins 動態規劃多重部分和問題

變形 價值 span 維數 text 推出 遞推 pro cal 原題鏈接:http://poj.org/problem?id=1742 題目大意:tony現在有n種硬幣,第i種硬幣的面值為A[i],數量為C[i]。現在tony要使用這些硬幣去買一塊價格不超過m的表。他希望

動態規劃背包問題-01背包+完全背包+多重背包

自己 動態規劃 問題 動態 重復 -- 今天 code i++ 01背包 有n種不同的物品,每種物品分別有各自的體積 v[i],價值 w[i] 現給一個容量為V的背包,問這個背包最多可裝下多少價值的物品。 1 for(int i = 1; i <= n; i++)

DAG上的動態規劃嵌套矩形問題

style printf 硬幣 介紹 == 矩形 n) clas 歸約 據說DAG是動態規劃的基礎,想一想還真的是這樣的,動態規劃的所有狀態和轉移都可以歸約成DAG DAG有兩個典型模型,一個是嵌套矩形問題一個是硬幣問題,這裏僅介紹一個嵌套矩形問題 等二輪復習的時候再補上

2018.8.17 題解 2018暑假集訓編輯距離

msu type ring clu span 插入 pan -h 俄羅斯 應該是一個很經典的題目了吧 上題面描述 概念 字符串的編輯距離,又稱為Levenshtein距離,由俄羅斯的數學家Vladimir Levenshtein在1965年提出。是指利用字符操作,