BUCT校赛的H题,动态规划能过,可惜当时没想到
题目连接:http://coder.buct.edu.cn:8088/JudgeOnline/problem.php?id=2184
BUCT 2184: 编辑距离
时间限制: 1 Sec 内存限制: 128 MB
提交: 20 解决: 7
[提交][状态][论坛]
题目描述
模式匹配算法解决了两个字符串的精确匹配问题,现实生活中,有很多情况需要我们处理“相似”而非“相等”的匹配,如DNA分析、拼写纠错等。
接下来我们要处理两个字符串的非精确匹配问题,首先定义一个代价函数,衡量两个字符串“差的有多远”,即两个字符串之间的距离度量,其中一个合理的距离度量是把一个字符串变到另一个字符串所需的最小修改次数,修改方式有以下三种:
替换:将字符串s中的一个字符替换成另外一个字符,例如把shot变成spot
插入:在字符串s中插入一个字符,例如把ago变成agog
删除:在字符串s中删除一个字符,例如把hour变成our
这个将s修改为t的最小修改次数就是s到t的编辑距离。
给定两个字符串s和t,你的任务是计算s到t编辑距离。
如样例输入的两个字符串的编辑距离是5,具体过程是:删除第一个t,把h替换成y,接下来的5个字符不变,然后插入一个o,把a替换成u,接下来的1个字符不变,把t替换成d,最后4个字符不变。
输入
两行字符串s和t,每行字符串不超过200个字符。
输出
输出包括一行整数,即s到t的编辑距离。
样例输入
thou shalt not
you should not
样例输出
5
感觉这题应该用DP会更方便一点,不过比赛时没往那方面想,赛后再别人的启发下才想到的。
整个DP过程跟最长公共子序列挺像的,相当于是它的逆过程。
有字符串 s1,s2;
设dp[i][j] 为 s1 中长度为 i的子串,和s2中长度为j的子串中 需要作出的修改次数。
则
当s1[i]==s2[j]时 dp[i][j]=dp[i-1][j-1] ,相当于s1 s2串中j相等的那一位直接都不考虑了。
当s1[i]!=s2[j]时 dp[i][j]=min(dp[i][j-1]+1,dp[i-1][j]+1,dp[i-1][j-1]+1);
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int MAX=205;
int dp[MAX][MAX];
char s1[MAX];
char s2[MAX];
void solve()
{
int len1=strlen(s1);
int len2=strlen(s2);
for(int i=0;i<=len2;i++)
{
dp[0][i]=i;
}
for(int i=0;i<=len1;i++)
{
dp[i][0]=i;
}
for(int i=1;i<=len1;i++)
{
for(int j=1;j<=len2;j++)
{
int temp;
if(s1[i-1]==s2[j-1])
{
temp=dp[i-1][j-1];
}
else
{
temp=dp[i-1][j-1]+1;
temp=min(temp,dp[i][j-1]+1);
temp=min(temp,dp[i-1][j]+1);
}
dp[i][j]=temp;
}
}
cout<<dp[len1][len2]<<endl;
}
int main()
{
while(gets(s1))
{
gets(s2);
solve();
}
return 0;
}