编辑距离问题
来源:互联网 发布:网络视听审核员证书 编辑:程序博客网 时间:2024/05/26 09:56
编辑距离问题
给定两个字符串S和T,对于T我们允许三种操作:
(1) 在任意位置添加任意字符
(2) 删除存在的任意字符
(3) 修改任意字符
问最少操作多少次可以把字符串T变成S?
例如: S= “ABCF” T = “DBFG”
那么我们可以
(1) 把D改为A
(2) 删掉G
(3) 加入C
(2) 删掉G
(3) 加入C
所以答案是3。
输入
第1行:字符串a(a的长度 <= 1000)。第2行:字符串b(b的长度 <= 1000)。
输出
输出a和b的编辑距离
输入示例
kittensitting
输出示例
3
题解(转摘):
分析: 这个最少的操作次数,通常被称之为编辑距离。“编辑距离”一次本身具有最短的意思在里面。因为题目有“最短”这样的关键词,首先我们想到的是BFS。是的,当S的距离为m, T的距离为n的时候,我们可以找到这样的操作次数的界限:
(1) 把T中字符全删了,再添加S的全部字符,操作次数m + n。
(2) 把T中字符删或加成m个,再修改 操作次数最多 |n – m| + m。
虽然,我们找到了这样的上界,BFS从实际角度并不可行,因为搜索空间是指数的,这取决于S中的字符种类——具体的数量级不好估计。
这个问题之所以难,是难在有“添加”“删除”这样的操作,很麻烦。我们试试换个角度理解问题,把它看成字符串对齐的问题,事实上从生物信息学对比基因的角度,我们可以这样理解问题。
给定字符串S和T,我们可以用一种特殊字符促成两个字符串的对齐。我们加的特殊字符是“-”, 我们允许在S和T中任意添加这种特殊字符使得它长度相同,然后让这两个串“对齐”,最终两个串相同位置出现了不同字符,就扣1分,我们要使得这两个串对齐扣分尽量少。
对于例子 我们实际上采取了这样的对齐方式:
12345
ABCF-
DB-FG
注意:如果要对齐,两个“-”相对是没有意义的,所以我们要求不出现这种情况。
那么看一下:
(1) S,T对应位置都是普通字符,相同,则不扣分。 例如位置2,4
(2) S,T对应位置都是普通字符,不同,则扣1分。 例如位置1
(3) S在该位置是特殊字符,T在该位置是普通字符,则扣1分,例如位置5
(4) S在该位置是普通字符,T在该位置是特殊字符,则扣1分,例如位置3
我们来看看扣分项目对应什么?
(1) 不扣分,直接对应
(2) 对应把T中对应位置的字符修改
(3) 对应在T中删除该字符
(4) 对应在T中添加该字符
好了,目标明确,感觉像不像 LCS?我们尝试一下:
设f(i,j)表示S的前i位和T的前j位对齐后的最少扣分。
那我们来看看最后一位,对齐的情况
(1) 必须S[i] == T[j], 这时前i – 1和j – 1位都已经对齐了,这部分肯定要最少扣分。这种情况下最少的扣分是f(i-1,j-1)
(2) 和(1)类似,S[i]≠T[j],这种情况下最少的扣分是f(i -1, j – 1) + 1
(3) S的前i位和T的前(j – 1)位已经对齐了,这部分扣分也要最少。这种情况下最少的扣分是f(i,j-1) + 1
(4) S的前(i-1)位已经和T的前j位对齐了,这部分扣分要最少。这种情况下最少的扣分是f(i,j-1) + 1
具体f(i,j)取什么值,显然是要看哪种情况的扣分最少。
给定字符串S和T,我们可以用一种特殊字符促成两个字符串的对齐。我们加的特殊字符是“-”, 我们允许在S和T中任意添加这种特殊字符使得它长度相同,然后让这两个串“对齐”,最终两个串相同位置出现了不同字符,就扣1分,我们要使得这两个串对齐扣分尽量少。
对于例子 我们实际上采取了这样的对齐方式:
12345
ABCF-
DB-FG
注意:如果要对齐,两个“-”相对是没有意义的,所以我们要求不出现这种情况。
那么看一下:
(1) S,T对应位置都是普通字符,相同,则不扣分。 例如位置2,4
(2) S,T对应位置都是普通字符,不同,则扣1分。 例如位置1
(3) S在该位置是特殊字符,T在该位置是普通字符,则扣1分,例如位置5
(4) S在该位置是普通字符,T在该位置是特殊字符,则扣1分,例如位置3
我们来看看扣分项目对应什么?
(1) 不扣分,直接对应
(2) 对应把T中对应位置的字符修改
(3) 对应在T中删除该字符
(4) 对应在T中添加该字符
好了,目标明确,感觉像不像 LCS?我们尝试一下:
设f(i,j)表示S的前i位和T的前j位对齐后的最少扣分。
那我们来看看最后一位,对齐的情况
(1) 必须S[i] == T[j], 这时前i – 1和j – 1位都已经对齐了,这部分肯定要最少扣分。这种情况下最少的扣分是f(i-1,j-1)
(2) 和(1)类似,S[i]≠T[j],这种情况下最少的扣分是f(i -1, j – 1) + 1
(3) S的前i位和T的前(j – 1)位已经对齐了,这部分扣分也要最少。这种情况下最少的扣分是f(i,j-1) + 1
(4) S的前(i-1)位已经和T的前j位对齐了,这部分扣分要最少。这种情况下最少的扣分是f(i,j-1) + 1
具体f(i,j)取什么值,显然是要看哪种情况的扣分最少。
为了方便,我们定义函数same(i,j)表示如果S[i] == T[j]则为0,否则为1。
我们来表示一下递推式:
f(i,j) = min(f(i – 1, j – 1) + same(i,j), f(i – 1,j ) + 1, f(i, j – 1) + 1)
初值是什么?
f(0, j) = j
f(i, 0) = i
这时因为对于S的前0位,我们只能在之前加入“-”,或者说把T全部删掉了。类似地,对于T地前0位,我们只能把S的字符都加进来,别无选择。
注意上述两个式子的重合点 f(0,0) = 0也符合我们的定义,并不矛盾。
我们来表示一下递推式:
f(i,j) = min(f(i – 1, j – 1) + same(i,j), f(i – 1,j ) + 1, f(i, j – 1) + 1)
初值是什么?
f(0, j) = j
f(i, 0) = i
这时因为对于S的前0位,我们只能在之前加入“-”,或者说把T全部删掉了。类似地,对于T地前0位,我们只能把S的字符都加进来,别无选择。
注意上述两个式子的重合点 f(0,0) = 0也符合我们的定义,并不矛盾。
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAX=1e3+10;int dp[MAX][MAX];int main(){ char str1[MAX] , str2[MAX]; scanf("%s %s",str1+1,str2+1); str1[0] = str2[0] = '0'; int k1 = strlen(str1)-1, k2 = strlen(str2)-1; memset(dp , 0 ,sizeof(dp)); for(int i = 0; i <= max(k1,k2) ; i++) //赋初值 dp[0][i] = dp[i][0] = i; for(int i = 1; i <= k1; i++) for(int j = 1; j <= k2; j++) { if(str1[i] == str2[j]) dp[i][j] = dp[i-1][j-1]; else dp[i][j] = dp[i-1][j-1] + 1; dp[i][j] = min( min(dp[i-1][j]+1, dp[i][j-1]+1) , dp[i][j]); } printf("%d\n",dp[k1][k2]); return 0; }
阅读全文
0 0
- 编辑距离问题
- 【dp】编辑距离问题
- 王晓东 编辑距离问题
- 编辑距离问题 dp
- 编辑距离问题
- 王晓东 编辑距离问题
- 编辑距离问题
- 编辑距离问题
- 编辑距离问题(1)
- 编辑距离问题
- DP_编辑距离问题
- 编辑距离问题(1)
- 编辑距离问题
- 编辑距离问题
- 编辑距离问题
- 编辑距离问题
- dp 编辑距离问题
- 编辑距离问题
- HDU-4300Clairewd’s message
- 软件测试的分类和分级
- 项目第七天
- 系统架构之高可用和高并发粗略处理方案
- Hdu 2204
- 编辑距离问题
- SQL LIKE操作符
- three.js全景视频
- HDU4237 The Rascal Triangle
- DNS
- C++知识总结(4)
- find the most comfortable road||HDU1598
- Just a Hook (HDU
- 数据源--Springboot配置使用Druid数据源