字符串编辑距离

题目描述
UNIX系统下有一个行编辑器ed,它每次只对一行文本做删除一个字符、插入一个字符或替换一个字符三种操作。例如某一行的内容是“ABC”,经过把第二个字符替换成“D”、删除第一个字符、末尾插入一个字符“B”,这三步操作后,内容就变成了“DCB”。即“ABC”变成“DCB”需要经过3步操作,我们称它们的编辑距离为3。
现在给你两个任意字符串(不包含空格),请帮忙计算它们的最短编辑距离。
输入描述:
输入包含多组数据。

每组数据包含两个字符串m和n,它们仅包含字母,并且长度不超过1024。
输出描述:
对应每组输入,输出最短编辑距离。

分析:
使用dp[i][j]代表字符串将串str1[0…i-1]转换为串str2[0…j-1]所需的最少操作次数(最短距离)

iteration:
d p [ i ] [ j ] = { d p [ i − 1 ] [ j ] + 1 , 插 入 d p [ i ] [ j − 1 ] + 1 , 删 除 d p [ i − 1 ] [ j − 1 ] + ( s t r 1 [ i − 1 ] ! = s t r 2 [ j − 1 ] ) 替 换 dp[i][j] = \left\{ \begin{array}{lr} dp[i-1][j]+1, & 插入 \\ dp[i][j-1] +1, & 删除 \\ dp[i-1][j-1] + (str1[i-1] != str2[j-1]) & 替换 \end{array} \right. dp[i][j]=dp[i1][j]+1,dp[i][j1]+1,dp[i1][j1]+(str1[i1]!=str2[j1])
base:
d p [ i ] [ 0 ] = i , d p [ 0 ] [ j ] = j . dp[i][0] = i, \\ dp[0][j] = j. dp[i][0]=i,dp[0][j]=j.

#include 
#include 
#include 
#include 
using namespace std;

int dp[1025][1025];
int main(){
    string str1, str2;
    while(cin >> str1 >> str2){
        memset(dp, 0, sizeof(dp));
        for(int i = 1; i <= str1.size(); ++i) dp[i][0] = i;
        for(int j = 1; j <= str2.size(); ++j) dp[0][j] = j;
        for(int i = 1; i <= str1.size(); ++i){
            for(int j = 1; j <= str2.size(); ++j){
                dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1);
                dp[i][j] = min(dp[i][j], dp[i-1][j-1] + (str1[i-1] != str2[j-1]));
            }
        }

        cout << dp[str1.size()][str2.size()] << endl;

        for(int i = 1; i <= str1.size(); ++i){
            for(int j = 1; j <= str2.size(); ++j){
                cout << dp[i][j] << ' ';
            } cout <<endl;
        }
    }
    return 0;
}

LeetCode上的相同题目:https://leetcode.com/problems/edit-distance/
因为dp[i][j]在更新的时候只与dp[i-1]这一行有关,所以我们可以进一步压缩空间利用率至 O ( m i n ( m , n ) ) O(min(m, n)) O(min(m,n)),其中 m m m, n n n为两个字符串的长度。

class Solution {
public:
   int minDistance(string word1, string word2) {
        if(word1.size() == 0) return word2.size();
        if(word2.size() == 0) return word1.size();
        /* const修饰的是char, 指针指向的内容不能改变, 指针可以改变 */
        const char* str1 = word1.c_str();  
        const char* str2 = word2.c_str();
        int len1 = word1.size(), len2 = word2.size();
        if(word1.size() < word2.size()) {
            swap(str1, str2);
            swap(len1, len2);
        }
        vector<int> dp(len2+1);
        int pre;  // dp[i-1][j-1]
        int candi;  // new dp[i][j]
       for(int j = 1; j <= len2; ++j) dp[j] = j;  // dp[0][j], 当i==1时用来更新pre 
       for(int i = 1; i <= len1; ++i){
            dp[0] = i; // dp[i][0] = i
            pre = i-1;  // dp[i-1][0]
            for(int j = 1; j <= len2; ++j){
                candi = min(dp[j],  dp[j-1]) + 1;  // dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + 1
                candi = min(candi, pre + (str1[i-1] != str2[j-1]));  // dp[i][j] = min(dp[i][j], dp[i-1][j-1]) + (str1[i-1]!= str2[j-1])
                pre = dp[j];  // record dp[i-1][j-1]
                dp[j] = candi;
            }
        } return dp[len2];
    }
};

参考链接:
https://www.jianshu.com/p/7ed1ba268d77
https://blog.csdn.net/yutianzuijin/article/details/50273335

你可能感兴趣的:(数据结构,算法)