求字符串的相似度
时间:2010-04-23 来源:pkuwwt
这是一个递归或动态规划的问题。比如长度分别为m,n的字符串str1和str2,其编辑距离为d(m,n), 则显然有
d(m,n) = min((str1[m]==str2[n])?d(m-1,n-1):d(m-1,n-1)+1, |
其意思是,编辑距离只与三种情况有关。假设将str1转化为str2: 第一种情况,让str1的前m-1个字符和str2的前n-1个字符进行转化,str1最后一个字符替换成str2最后一个字符。这样(str1[m]==str2[n])?d(m-1,n-1):d(m-1,n-1)+1这一句就好理解了。即两字符串最后一个字符相等的话,就用不着替换,否则就要替换。 第二种情况,将str1转化为str2的前n-1个字符,然后插入str2最后一个字符,变成str2。其编辑步骤数显然是d(m,n-1)+1。 第三种情况,和第二种情况类似,将str1的前m-1个字符转化为str2,然后删除str1最后一个字符。
这三种情况各得到一个编辑步骤数,取其最小值即可。 这样,我们得到一个递归式。其初始条件是
d(0,k)=k, 1<=k<=n |
因此,我们就可以据此递推式构造一个动态规划过程,假设两个字符串分别为"china"和"unix",则
|
c | h | i | n | a | |
0 | 1 | 2 | 3 | 4 | 5 | |
u | 1 | 1 | 2 | 3 | 4 | 5 |
n | 2 | 2 | 2 | 3 | 3 | 4 |
i | 3 | 3 | 3 | 2 | 3 | 4 |
x | 4 | 4 | 4 | 3 | 3 | 4 |
图中黑色加粗部分是初始值,而红色部分是一条可能的路径。若将"china"变成"unix",则可能的步骤是 c->u, h->n, delete n, a->x
编程实现时,可以直接在一个矩阵中进行。但为节约空间,也可以只用两个数组,每次更新一行。但要注意,较长的字符串要置于水平方向。
#include<iostream> |