算法导论.docx

上传人:b****3 文档编号:5264557 上传时间:2022-12-14 格式:DOCX 页数:10 大小:315.70KB
下载 相关 举报
算法导论.docx_第1页
第1页 / 共10页
算法导论.docx_第2页
第2页 / 共10页
算法导论.docx_第3页
第3页 / 共10页
算法导论.docx_第4页
第4页 / 共10页
算法导论.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

算法导论.docx

《算法导论.docx》由会员分享,可在线阅读,更多相关《算法导论.docx(10页珍藏版)》请在冰豆网上搜索。

算法导论.docx

算法导论

算法1

算法导论 15-3 动态规划求最短编辑距离

(2010-07-1519:

35:

23)

转载▼

描述:

设A和B是2个字符串。

要用最少的字符操作将字符串A转换为字符串B。

这里所说的字符操作包括:

(1)删除一个字符;

(2)插入一个字符;

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

将字符串A变换为字符串B所用的最少字符操作数称为字符串A到B的编辑距离,记为d(A,B)。

试设计一个有效算法,对任给的2个字符串A和B,计算出它们的编辑距离d(A,B)。

(2)7

要求:

输入:

第1行是字符串A,第2行是字符串B。

输出:

字符串A和B的编辑距离d(A,B)

 

思路:

开一个二维数组d[i][j]来记录a0-ai与b0-bj之间的编辑距离,要递推时,需要考虑对其中一个字符串的删除操作、插入操作和替换操作分别花费的开销,从中找出一个最小的开销即为所求

具体算法:

首先给定第一行和第一列,然后,每个值d[i,j]这样计算:

d[i][j]  =  min(d[i-1][j]+1,d[i][j-1]+1,d[i-1][j-1]+(s1[i] == s2[j]?

0:

1));  

 最后一行,最后一列的那个值就是最小编辑距离 

 

poj3356类似题目:

c++代码:

#include

usingnamespacestd;

intlen1,len2;//分别代表原string与目标string的长度

chars[1005],d[1005];//分别存储原string与目标string

intdp[1001][1001];

inlineintMax(inta,intb)

{

 returna>b?

a:

b;

}

inlineintMin(inta,intb)

{

 returna

a:

b;

}

voidDp()

{

 inti,j;

 for(i=0;i<=Max(len1,len2);i++)

 {

  dp[i][0]=i;

  dp[0][i]=i;

 }

 for(i=1;i<=len1;i++)

  for(j=1;j<=len2;j++)

  {

   if(s[i-1]==d[j-1])

    dp[i][j]=dp[i-1][j-1];//不需操作

   else

    dp[i][j]=Min(dp[i][j-1]+1,Min(dp[i-1][j]+1,dp[i-1][j-1]+1));

  }

 cout<

}

intmain(void)

{

 //freopen("in.txt","r",stdin);

 while(cin>>len1>>s)

 {

  cin>>len2>>d;

  Dp();

 }

 return0;

}

动态规划求编辑距离http:

//qinxuye.me/article/get-edit-distance-by-dynamic-programming/

发表于2011年4月21日8:

12p.m.  位于分类一箩筐

这两天在写一个简单的单词拼写检查器(Spellchecker),本来求编辑距离只是其中的一个子问题,现在把它罗列出来,是因为鉴于看到一些书,把本来不是很难的问题讲得很复杂,而且不知道是不是一些作者,为了显得自己水平之高,几乎没有任何的推导,只有一堆结果罗列。

当然这些都是题外话了,但是,书者,传道授业解惑也,若是使读者迷惑不能自拔,不知是读者愚钝,还是书之不书。

现在我们开始切入正题。

先来说说什么是编辑距离,编辑距离是一种字符串之间相似程度的计算方法。

按照Damerau给出的定义,即两个字符串之间的编辑距离等于使一个字符串变成另外一个字符串而进行的

(1)插入、

(2)删除、(3)替换或(4)相邻字符交换位置而进行操作的最少次数。

用ed来表示编辑距离。

比如:

ed("recoginze","recognize")==1(需要交换两个相邻字符"i"和"n"的位置)

ed("sailn","failing")==3(需要将"s"换成"f",在字母"l"后边插入"i","n"后面插入"g")。

有的时候,变换并不唯一,重要的是要求出这一些变换路径中最短的数量。

关于编辑距离的求法,普遍的采用的是动态规划方法。

但是,目前网上的资料中提及的编辑路径并不准确,缺少了第(4)步的处理。

详细的同学们可以查阅这两篇文章——【串和序列处理2】字符串编辑距离算法(Java)和动态规划求编辑距离——算法解题报告(C++)。

下面给出维基上对动态规划的定义:

动态规划是一种在数学和计算机科学中使用的,用于求解包含重叠子问题的最优化问题的方法。

其基本思想是,将原问题分解为相似的子问题,在求解的过程中通过子问题的解求出原问题的解。

其实就是把一个复杂的最优解问题分解成一系列较为简单的最优解问题,再将较为简单的最优解问题一步步分解,直到能够一眼看出为止。

我们拿"sailn"和"failing"这两个字符串作例子。

首先我们定义这样一个函数——edit(i,j),它表示字符串1的长度为i的子串到字符串2的长度为j的子串的编辑距离。

首先我们作出初始化edit(0,j)=j(字符串1子串长度为0,字符串2子串有多少个字符,就作多少次增加操作;于是同理,edit(i,0)=i。

这里,我们要注意到对于操作(4),即交换相邻字符串的操作,我们要把某个字符通过这个操作到另一个位置上,我们最多只能执行一次操作,即只能移动到邻位上。

原因是什么呢?

这是因为,移动两次的话,就没有优势了,它的操作等于两次替换操作的操作数。

大于2次的时候,移动操作会更差。

所以,我们要进行操作(4),最多只发生一次操作。

我们可以得出这样一段动态规划公式:

1.如果i==0且j==0,edit(i,j)=0

2.如果i==0且j>0,edit(i,j)=j

3.如果i>0且j==0,edit(i,j)=i(2、3点之前已经陈述)

4.如果0

5.如果i>1且j>1时,这个时候可能出现操作(4),由之前的推导,我们只能交换一次,否则就没有意义。

这个时候在比较最小值中可能加入edit(i-2,j-2)+1,什么时候加入呢?

假设i-2长度的字符串1子串和j-2长度的字符串2子串已经得出最优解,这个时候如果s1[i-1]==s2[j]并且s1[i]==s2[j-1],这时就在比较值中加入edit(i-2,j-2)+1(这个1是交换一次的操作)

我们来把这个过程演绎一遍。

我们首先给出这样一个矩阵:

 

 

0

f

a

i

l

i

n

g

0

 

 

 

 

 

 

 

 

s

 

 

 

 

 

 

 

 

a

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

l

 

 

 

 

 

 

 

 

n

 

 

 

 

 

 

 

 

在经过初始化之后,矩阵变成这样:

 

0

f

a

i

l

i

n

g

0

0

1

2

3

4

5

6

7

s

1

 

 

 

 

 

 

 

a

2

 

 

 

 

 

 

 

i

3

 

 

 

 

 

 

 

l

4

 

 

 

 

 

 

 

n

5

 

 

 

 

 

 

 

现在要计算edit(1,1),而edit(0,1)+1==2,edit(1,0)+1==2,edit(0,0)+f(1,1)==0+1==1,他们其中最小的为1,因此edit(1,1)==1。

按照此法计算,直到计算到edit(2,2),矩阵为这样:

 

0

f

a

i

l

i

n

g

0

0

1

2

3

4

5

6

7

s

1

1

2

3

4

5

6

7

a

2

2

 

 

 

 

 

 

i

3

 

 

 

 

 

 

 

l

4

 

 

 

 

 

 

 

n

5

 

 

 

 

 

 

 

这个时候,edit(2,1)+1==3,edit(1,2)+1==3,edit(1,1)+f(2,2)==1+0==1,而此时s1[2]=='a'而s2[1]=='f'‘,不满足条件,所以,交换相邻字符的操作不纳入比较最小数中计算。

接着往下计算,得出最后矩阵为:

 

0

f

a

i

l

i

n

g

0

0

1

2

3

4

5

6

7

s

1

1

2

3

4

5

6

7

a

2

2

1

2

3

4

5

6

i

3

3

2

1

2

3

4

5

l

4

4

3

2

1

2

3

4

n

5

5

4

3

2

2

2

3

可以看到edit(len(s1),len(s2))==3,验证了先前的结论。

接下来就给出Python实现的代码:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

#!

/usr/bin/envpython

#-*-coding:

utf-8-*-

 

defed(s1,s2):

    '''

    >>>ed('eeba','abac')

    3

    >>>ed('abc','cba')

    2

    >>>ed('cbc','eba')

    2

    >>>ed('recoginze','recognize')

    1

    >>>ed('sailn','failing')

    3

    >>>ed('ab','ba')

    1

    '''

    #动态规划求编辑距离

    #params1:

字符串1

    #params2:

字符串2

     

    len1=len(s1)

    len2=len(s2)

     

    #初始化矩阵

    matrix=[[i+jforjinrange(len2+1)]foriinrange(len1+1)]

     

    forrowinrange(len1):

        forcolinrange(len2):

            comp=[matrix[row+1][col]+1,matrix[row][col+1]+1]

             

            ifs1[row]==s2[col]:

                comp.append(matrix[row][col])

            else:

                comp.append(matrix[row][col]+1)

             

            #对相邻字符交换位置的处理判断

            ifrow>0andcol>0:

                ifs1[row]==s2[col-1]ands1[row-1]==s2[col]:

                    comp.append(matrix[row-1][col-1]+1)

                     

            matrix[row+1][col+1]=min(comp)

             

    returnmatrix[len1][len2]

重要的是这段代码:

?

1

2

3

ifrow>0andcol>0:

    ifs1[row]==s2[col-1]ands1[row-1]==s2[col]:

        comp.append(matrix[row-1][col-1]+1)

同学们要用其他语言实现,只需要实现以上判断,来进行操作(4)。

注意到ed函数的docstring出现了类似命令行的句子,这是为了方便进行doctest测试。

要测试全部数据,只需加上以下几句话:

?

1

2

3

if__name__=='__main__':

    importdoctest

    doctest.testmod()

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 机械仪表

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1