算法作业14——字符串编辑距离(期末大作业)

1. 

给定一个源串和目标串,能够对源串进行如下操作:

1在任意位置上插入一个字符;

2替换任意字符;

3删除任意字符。

 

例如:kitten > sitting

操作

源串

目标串

替换:k > s

kitten

sitten

替换:e > i

sitten

sittin

插入:g

sittin

sitting

写一个程序,实现返回最小操作次数,使得对源串进行上述这些操作后等于目标串(源串和目标串的长度都小于2000)。

 

2. 解析

本题我选择的求解思路是动态规划。

设s1,s2是两个字符串,其中s1是源串,s2是目标串,s1字符串长度是len1,s2字符串的长度是len2;

dp[i][j]是s1[1,2,...,i]通过插入、替换、删除得到s2[1,2,...,j]的最少操作次数,最后的dp[len1][len2]就是从s1字符串变换到s2字符串的最小操作次数。dp[i][j]的值满足以下等式:

 

实例:aacag > aatat

 

a

a

t

a

t

0

1

2

3

4

5

a

1

0

1

2

3

4

a

2

1

0

1

2

3

c

3

2

1

1

2

3

a

4

3

2

2

1

2

g

5

4

3

3

2

2

                                  dp

 

(1)初始化:dp[0][j=0,...,s1.length]=j;

dp[i=0,...,s2.length][0]=i;

(2)i=1

s1[1]=s2[1] => dp[1][1]=dp[0][0]=0

s1[1]=s2[2] => dp[1][2]=dp[0][1]=1 插入a

s1[1]<>s2[3] => dp[1][3]=min{dp[0][2],dp[1][2],dp[0][3]}+1=2 插入a,t

s1[1]=s2[4] => dp[1][4]=dp[0][3]=3 插入a,t,a

s1[1]<>s2[5] => dp[1][5]=min{dp[0][4],dp[1][4],dp[0][5]}+1=4 插入a,t,a,t

(3)i=2

s1[2]=s2[1] => dp[2][1]=dp[1][0]=1 删除a 

s1[2]=s2[2] => dp[2][2]=dp[1][1]=0 

s1[2]<>s2[3] => dp[2][3]=min{dp[1][2],dp[1][3],dp[2][2]}+1=1 插入t

s1[2]=s2[4] => dp[2][4]=dp[1][3]=2  插入t,a

s1[2]<>s2[5] => dp[2][5]=min{dp[1][4],dp[1][5],dp[2][4]}+1=3 插入t,a,t

(4)i=3 

s1[3]<>s2[1] => dp[3][1]=min{dp[2][0],dp[3][0],dp[2][1]}+1=2 删除a,c 

s1[3]<>s2[2] => dp[3][2]=min{dp[2][1],dp[3][1],dp[2][2]}+1=1 删除c 

s1[3]<>s2[3] => dp[3][3]=min{dp[2][2],dp[3][2],dp[2][3]}+1=1 替换c —> t

s1[3]<>s2[4] => dp[3][4]=min{dp[2][3],dp[3][3],dp[2][4]}+1=2 替换c —> t,插入a 

s1[3]<>s2[5] => dp[3][5]=min{dp[2][4],dp[3][4],dp[2][5]}+1=3 替换c —> t,插入a,t

(5)i=4 

s1[4]=s2[1] => dp[4][1]=dp[3][0]=3 删除a,a,c 

s1[4]=s2[2] => dp[4][2]=dp[3][1]=2 删除a,c

s1[4]<>s2[3]=>dp[4][3]=min{dp[3][2],dp[4][2],dp[3][3]}+1=2 删除a,替换c—>t或删除c,替换a—>t

s1[4]=s2[4] => dp[4][4]=dp[3][3]=1 替换c—> t

s1[4]<>s2[5] => dp[4][5]=min{dp[3][4],dp[4][4],dp[3][5]}+1=2 替换c—> t,插入t

(6)i=5 

s1[5]<>s2[1] => dp[5][1]=min{dp[4][0],dp[5][0],dp[4][1]}+1=4 删除a,c,a,g 

s1[5]<>s2[2] => dp[5][2]=min{dp[4][1],dp[5][1],dp[4][2]}+1=3 删除c,a,g

s1[5]<>s2[3] => dp[5][3]=min{dp[4][2],dp[5][2],dp[4][3]}+1=3 替换c—> t,删除a,g或替换a—> t,删除c,g或替换g —> t,删除a,c 

s1[5]<>s2[4] => dp[5][4]=min{dp[4][3],dp[5][3],dp[4][4]}+1=2 替换c—> t,删除g或替换g—> t,删除c 

s1[5]<>s2[5] => dp[5][5]=min{dp[4][4],dp[5][4],dp[4][5]}+1=2 替换c —> t,替换g —> t  

 

所以从源串aacag变换到目标串aatat的最小操作次数是dp[5][5]=2

3. 设计

(1)输入源串s1,目标串s2

(2)len1=s1.length(),len2=s2.length()

(3) oper()

dp[i=0,1, ... , len1][0]=i;//初始化

dp[0][j=0,1, ... ,len2]=j;//初始化

For i = 1 to len1

For j = 1 to len2

//字符相同,不操作

If s1[i-1]=s2[j-1] then dp[i][j]=dp[i-1][j-1]

//字符不同,在原有的最小操作数的基础上+1

Else dp[i][j]=min{dp[i-1][j-1],dp[i-1][j],dp[i][j-1]}+1;

Return dp[len1][len2]

(4)输出dp[len1][len2]

4.分析

如上设计,两层for循环即可解题,所以

设源串字符串长度为m,目标串长度为n,则时间复杂度=O(m*n)

5.源码

https://github.com/2579081436/algorithm.github.io

posted @ 2021-06-07 02:27  Caecae_with_island  阅读(269)  评论(0编辑  收藏  举报