Leetcode#72 Edit Distance

原题地址

 

教科书般经典的动归题目,也可以看作是地图寻路问题。例如word1="ceab",word2="abc",构造如下地图。其中"^"表示起点,"$"表示终点,则题目转化成了寻找一条从起点到终点的最短路径。

           a b c  <- word2

word1 -> c ^ . .

         e . . .

         a . . .

         b . . $

 

对于地图上任意坐标为(i,j)的点,可以:

1. 向右走一步,表示跳过word2的一个字符,即删除一个word2的字符或向word1插入一个字符。

2. 向下走一步,表示跳过word1的一个字符,即删除一个word1的字符或向word2插入一个字符。

3. 向右下走一步,表示同时跳过word1和word2的一个字符,即修改一个word1或word2的字符,如果这两个字符本来就相等则不用修改。

 

令distance[i][j]表示从该点到终点的最短距离(也就是word1[i..n]和word2[j..m]的编辑距离),则有递推公式:

distance[i][j] = min{distance[i+1][j] + 1, distance[i][j+1] + 1, distance[i+1][j+1] + (word1[i] == word2[j] ? 0 : 1)}

 

具体实现中,由于递推公式只用到了相邻层的结果,所以可以压缩状态,用一维数组保存distance。

代码:

 1 int minDistance(string word1, string word2) {

 2   int len1 = word1.length();

 3   int len2 = word2.length();

 4 

 5   if (len1 < len2)

 6     return minDistance(word2, word1);

 7   if (len2 == 0)

 8     return len1;

 9 

10   vector<int> distance(len1 + 1, 0);

11   for (int j = len2; j >= 0; j--)

12     distance[j] = len2 - j;

13   int rd = 0; // 表示distance[i+1][j+1]

14 

15   for (int i = len1 - 1; i >= 0; i--) {

16     rd = distance[len2];

17     distance[len2] = len1 - i;

18     for (int j = len2 - 1; j >= 0; j--) {

19       int tmp = distance[j];

20       distance[j] = min(distance[j] + 1, distance[j + 1] + 1);

21       distance[j] = min(distance[j], rd + (word1[i] == word2[j] ? 0 : 1));

22       rd = tmp;

23     }

24   }

25 

26   return distance[0];

27 }

 

你可能感兴趣的:(LeetCode)