求算两个字符串之间的编辑距离

本文介绍了如何通过动态规划算法来计算两个字符串之间的编辑距离,详细解释了算法原理,并给出了具体的Java代码实现。

简述:

设A和B是两个字符串,要用最少的字符操作将字符串A转换为字符串B

字符串操作包括,

1)删除一个字符

2)插入一个字符

3)将一个字符改为另一个字符


算法:

模拟构造一个(m + 1)行,(n+1)列的表格

每一次都是在前一次的计算结果下,得到当前的值

首先是三个特殊情况 用srcStr表示源字符串,dstStr 表示目标字符串

1)    两个空字符串的编辑距离D(srcStr, dstStr) = 0

2)   如果srcStr为空,dstStr不为空,则D(srcStr, dstStr) = dstStr.length(), 即在原空字符串上添加字符,形成dstStr

3)   如果dstStr为空,srcStr不为空,则D(srcStr, dstStr) = srcStr.length(), 及在源字符串上删除其所有字符,直至为空


例子:

下面实际解决一下从srcStr = "bd"  到 dstStr = "abcd"的过程

上面这三种情况分别是初始化的时候要做的

首先用一维数组表示两位数组

纵向 i = 0 -> m+1 , d[i * (n + 1)] = i 

横向 i = 0 -> n+1, d[i] = i

即:如下图是初始化之后的表格信息,纵向是b,d   横向是a,b,c,d



步骤:

for(i = 1 -> 2)     //  2为“bd"的长度

      for( j = 1 -> 4 )   // 4 为”abcd"的长度

为了确定d[ i ][ j ]的大小, 需要比较

a)  从d[ i - 1 ][j - 1] 修改字符srcStr[i - 1], 使之变为dstStr[j - 1], 如果srcStr[i - 1] == dstStr[j - 1] 则这一步可以免去

b)  从d[ i - 1 ][ j ]  在srcStr的[ i - 1]处添加一个字符,使字符srcStr[ i - 1 ]变为dstStr[ j - 1 ]

c)  从d[ i ][ j - 1 ] 在dstStr的[ j - 1 ]处删除一个字符, 使字符dstStr[ j - 1 ]变为srcStr[ i - 1]

三者之间的最小值赋给d[ i ][ j ]


代码:

[java] view plain
  1. package dynamic_programming;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.InputStreamReader;  
  7.   
  8. public class StringToString {  
  9.     public static void main(String[] args) {  
  10.         System.out.print("please input src String: ");  
  11.         InputStream inputStream = System.in;  
  12.         InputStreamReader inputStreamReader = new InputStreamReader(inputStream);     
  13.         BufferedReader bufferReader = new BufferedReader(inputStreamReader);  
  14.           
  15.         //Get source string  
  16.         String srcStr = null;    
  17.         try{    
  18.             srcStr = bufferReader.readLine();  
  19.         }catch(IOException e){    
  20.             e.printStackTrace();    
  21.         }  
  22.         //Get destination string  
  23.         String dstStr = null;  
  24.         System.out.print("please input dst String: ");  
  25.         try{    
  26.             dstStr = bufferReader.readLine();  
  27.         }catch(IOException e){    
  28.             e.printStackTrace();    
  29.         }  
  30.           
  31.         //Display the result  
  32.         System.out.println("Edit Distance is: "   
  33.                 + getEditDistance(srcStr, dstStr));  
  34.           
  35.         try{    
  36.             bufferReader.close();    
  37.             inputStreamReader.close();    
  38.             inputStream.close();    
  39.         }catch(IOException e){    
  40.             e.printStackTrace();    
  41.         }    
  42.     }  
  43.       
  44.     public static int getEditDistance(String srcStr, String dstStr){  
  45.         int m = srcStr.length();  
  46.         int n = dstStr.length();  
  47.         //use one dimension array to represent two dimension  
  48.         //Initializing...  
  49.         int d[] = new int[(m + 1) * (n + 1)];  
  50.         for(int i = 0;i <= m;i++)  
  51.             d[i * (n + 1)] = i;  
  52.         for(int i = 0;i <= n;i++)  
  53.             d[i] = i;  
  54.           
  55.         //Dynamic Programming...  
  56.         for(int i = 1; i <= m;i++){  
  57.             for(int j = 1; j <= n;j++){  
  58.                 int modifyDis = d[(i - 1) * (n + 1) + (j - 1)]  
  59.                           + (srcStr.charAt(i - 1) == dstStr.charAt(j - 1) ? 0 : 1);  
  60.                 int addDis = d[(i - 1) * (n + 1) + j] + 1;  
  61.                 int deleteDis = d[i * (n + 1) + (j - 1)] + 1;  
  62.                 d[i * (n + 1) + j] = Min(modifyDis, addDis, deleteDis);  
  63.             }  
  64.         }  
  65.           
  66.         //Display Result  
  67.         System.out.println("Result Array: ");  
  68.         for(int i = 0; i <= m;i++){  
  69.             for(int j = 0; j <= n;j++){  
  70.                 System.out.print("\t" + d[i * (n + 1) + j]);  
  71.             }  
  72.             System.out.println();  
  73.         }  
  74.           
  75.         return d[m * (n + 1) + n];  
  76.     }  
  77.       
  78.     public static int Min(int a, int b, int c){  
  79.         int result = a > b ? b : a;  
  80.         return result > c ? c : result;  
  81.     }  
  82. }  

输出测试:

### 三级标题:C语言实现两个字符串编辑距离计算 编辑距离(Levenshtein 距离)是指两个字符串之间由一个转变为另一个所需的最少单字符编辑操作次数,允许的操作包括插入、删除和替换字符。为了在 C 语言中实现该法,通常采用动态规划方法[^3]。 定义状态 `d[i][j]` 为字符串 `source` 前 `i` 个字符到字符串 `target` 前 `j` 个字符的编辑距离。状态转移方程如下: - 如果 `source[i-1] == target[j-1]`,则 `d[i][j] = d[i-1][j-1]`; - 否则 `d[i][j] = min(d[i-1][j] + 1, d[i][j-1] + 1, d[i-1][j-1] + 1)`。 初始条件为: - `d[0][j] = j`,表示将 `target` 前 `j` 个字符全部插入; - `d[i][0] = i`,表示将 `source` 前 `i` 个字符全部删除。 以下是基于上述逻辑的 C 语言实现: ```c #include <stdio.h> #include <string.h> #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) int edit_distance(const char *source, const char *target) { int len_source = strlen(source); int len_target = strlen(target); // 创建二维数组用于存储动态规划结果 int dp[len_source + 1][len_target + 1]; // 初始化边界值 for (int i = 0; i <= len_source; i++) { dp[i][0] = i; } for (int j = 0; j <= len_target; j++) { dp[0][j] = j; } // 动态规划填充数组 for (int i = 1; i <= len_source; i++) { for (int j = 1; j <= len_target; j++) { if (source[i - 1] == target[j - 1]) { dp[i][j] = dp[i - 1][j - 1]; } else { dp[i][j] = MIN(dp[i - 1][j], MIN(dp[i][j - 1], dp[i - 1][j - 1])) + 1; } } } return dp[len_source][len_target]; } int main() { const char *source = "kitten"; const char *target = "sitting"; printf("Edit distance between '%s' and '%s' is %d\n", source, target, edit_distance(source, target)); return 0; } ``` 此程序使用了一个二维数组 `dp` 来存储中间结果,并通过遍历字符串长度填充数组,最终得到两个字符串之间的最小编辑距离[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值