LeetCode OJ 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

Show Tags

这题刚开始感觉就是DP,后来看到了Discuss里面给出的pdf链接才知道怎么做。

我们令dp[i][j]表示word1的前i个字母和word2的前j个字母的差距数,那么:

Just felt that maybe dynamic programming should be used to solve this problem, but not until i read the pdf from the Discuss did i know how to use dp.

Define the dp[i][j] the edit distance between the first i letters from word1 and the first j letters from word2, we get:

http://www.stanford.edu/class/cs124/lec/med.pdf


我的AC代码:

My AC code:

class Solution {
public:
	int minDistance(string word1, string word2) {
		int s1 = word1.size(), s2 = word2.size();
		
		int ** dp;  // new an array
		dp = new int*[s1 + 1];
		for (int i = 0; i <= s1; i++) dp[i] = new int[s2 + 1];

		for (int i = 0; i <= s1; i++) dp[i][0] = i;  // initialise
		for (int i = 0; i <= s2; i++) dp[0][i] = i;

		for (int i = 1; i <= s1; i++) {
			for (int j = 1; j <= s2; j++) {
				dp[i][j] = min(min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + (word1[i - 1] != word2[j - 1]));
			}
		}

		int ans = dp[s1][s2];  // record the answer
		for (int i = 0; i < s1; i++) delete []dp[i];  // delete the array
		delete[]dp;
		return ans;
	}
};
如果我们需要知道是如何把word2改变成word1的应该如何做呢?

建立另外一个导向数组,回溯即可。

这是来用来研究的代码:

But what if we wanna know how to convert word2 to word1?

We can use an array to trace to get the answer.

Let's see this code(just add sth. from the above):

#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
using namespace std;

class Solution {
public:
	int minDistance(string word1, string word2) {
		int s1 = word1.size(), s2 = word2.size();

		int ** dp;  // new a dp array
		dp = new int*[s1 + 1];
		for (int i = 0; i <= s1; i++) dp[i] = new int[s2 + 1];

		for (int i = 0; i <= s1; i++) dp[i][0] = i;
		for (int i = 0; i <= s2; i++) dp[0][i] = i;

		string ** dir;  // new a direction array
		dir = new string*[s1 + 1];
		for (int i = 0; i <= s1; i++) dir[i] = new string[s2 + 1];

		for (int i = 0; i <= s1; i++) dir[i][0] = "Insert";  // insert sth. to word1
		for (int i = 0; i <= s2; i++) dir[0][i] = "Delete";  // delete sth. from word1
		dir[0][0] = " Start";  // begin the conversion

		for (int i = 1; i <= s1; i++) {
			for (int j = 1; j <= s2; j++) {
				int ins, del, rep;
				ins = dp[i - 1][j] + 1;
				del = dp[i][j - 1] + 1;
				rep = dp[i - 1][j - 1] + (word1[i - 1] != word2[j - 1]);
				if (ins <= del && ins <= rep) {
					dp[i][j] = ins;
					dir[i][j] = "Insert";
				}
				else if (del <= ins && del <= rep) {
					dp[i][j] = del;
					dir[i][j] = "Delete";
				}
				else if (rep <= ins && rep <= del) {
					dp[i][j] = rep;
					if (word1[i - 1] != word2[j - 1]) {
						dir[i][j] = "Change";  // change some letters in word2 to word1
					}
					else {
						dir[i][j] = "  Keep";  // keep some letters in word1 
					}
				}
			}
		}

		cout << "Steps:" << endl;  // show the dp array
		cout << "       #";
		for (int i = 0; i < s2; i++) cout << "      " << word2[i];
		cout << endl;
		for (int i = 0; i <= s1; i++) {
			cout << (i == 0 ? '#' : word1[i - 1]);
			for (int j = 0; j <= s2; j++) {
				cout << setw(7) << dp[i][j];
			}
			cout << endl << endl;
		}

		cout << "How: " << endl;  // show the direction array
		cout << "       #";
		for (int i = 0; i < s2; i++) cout << "      " << word2[i];
		cout << endl;
		for (int i = 0; i <= s1; i++) {
			cout << (i == 0 ? '#' : word1[i - 1]);
			for (int j = 0; j <= s2; j++) {
				cout << " " << dir[i][j];
			}
			cout << endl << endl;
		}

		cout << "From Word2 to Word1:" << endl;  // trace
		int si = s1, sj = s2;
		vector<string> fromWord2ToWord1;
		for (int i = 0; i < dp[s1][s2];) {
			fromWord2ToWord1.push_back(dir[si][sj]);
			if (dir[si][sj] != "  Keep") i++;
			if (dir[si][sj] == "Insert") si--;
			else if (dir[si][sj] == "Delete") sj--;
			else si--, sj--;
		}
		for (int i = fromWord2ToWord1.size() - 1; i >= 0; i--) {
			cout << fromWord2ToWord1[i] << (i ? " --> " : ".");
		}
		cout << endl << endl;

		int ans = dp[s1][s2];
		for (int i = 0; i < s1; i++) delete []dp[i];
		delete[]dp;
		return ans;
	}
};

int main() {
	Solution s;
	cout << "Ans:" << s.minDistance("abcdxabcdasde", "qwkvokasd");
	return 0;
}
让我们看看发生了什么:

这里的例子是word1="abcdxabcdasde",word2="qwkyokasd",注意我们是将word2转为word1,反过来情况类似 ;

dp数组的变化:

Notice that the word1 is "abcdxabcdasde" and the word2 is "qwkyokasd".

This is what happened in the dp array:


关键是dir数组:

And the point is the direction array:


最后我们便可以得到将word2转变为word1的方法:

At last we can figure out how to finish the conversion.


对应的具体方法:

The conversion:

Original: word1="abcdxabcdasde", word2="qwkyokasd".

1.Change: a w k y o k a s d;

2.Change: a b k y o k a s d;

3.Change: a b c y o k a s d;

4.Change: a b c d o k a s d;

5.Change: a b c d x k a s d;

6.Change: a b c d x a a s d;

7.Insert:     a b c d x a b a s d;

8.Insert:     a b c d x a b c a s d;

9.Insert:     a b c d x a b c d a s d;

10.Keep:   a b c d x a b c d a s d;

11.Keep:   a b c d x a b c d a s d;

12.Keep:   a b c d x a b c d a s d;

13.Insert:   a b c d x a b c d a s d e.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值