HDU 4271

字符串的编辑距离的扩展

//f[i,j]表示s[0...i]与t[0...j]的最小编辑距离。    
f[i,j] = min { f[i-1,j]+1,  f[i,j-1]+1,  f[i-1,j-1]+(s[i]==t[j]?0:1) }    

f[i-1,j]表示将s[i]删去,剩下是s[0...i-1]与t[0...j]的最小编辑距离;

f[i][j-1]表示在s[i]后面插入t[j],剩下是s[0...i]与t[0...j-1]的最小编辑距离

f[i-1][j-1]表示用s[i]去匹配t[j],匹配不上则替换,剩下是s[0...i-1]与t[0...j-1]的最小编辑距离

动态规划的初始化是:

f[-1][j] = j,表示插入t[0..j]到s头

f[i][-1] = i,表示删除s[0...i]

#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
char s[100100],tmp[100100],str[20][20],temp[100100];
int dp[100100][20];
int n,l1,l2;
int pos,ans;
int cal(char * s1,char * s2,int len1,int len2){  //这里dp[i][j]表示s2的0~j的字串成为s1的0~i的字串最小距离
    int i,j;
    //memset(dp,0,sizeof(dp));           //被MEMSET卡了!!!!!!
    //for(int i=0;i<=l1;i++)  如果这四行加上,dp[i][j]表示的是s1串前i位与s2前j位的全部匹配的编辑距离  
    //{  
    //    dp[i][0] = i;  
    //}  
    for(i=0;i<=len2;i++)
        dp[0][i]=i;
    for(i=1;i<=len1;i++)
        for(j=1;j<=len2;j++){
            dp[i][j]=min(min(dp[i][j-1],dp[i-1][j])+1,dp[i-1][j-1]+(s1[i-1]!=s2[j-1]));
        }
    int tem=20;
    for(i=1;i<=len1;i++)
        tem=min(tem,dp[i][len2]);
    return tem;
}
int main(){
    int i,j,k;
    while(scanf("%s",s)!=EOF){
        l1=strlen(s);
        strcpy(tmp,s);
        for(j=0;j<10 && j<l1;j++)
            tmp[l1+j]=s[j];
        tmp[l1+j]='\0';
        scanf("%d",&n);
        ans=20;
        for(i=1;i<=n;i++){
            scanf("%s",str[i]);
            l2=strlen(str[i]);
            if(l1>=l2*2){
                int tem=cal(tmp,str[i],l1+l2,l2);
                if(tem<ans){
                    ans=tem;
                    pos=i;
                }
                else if(tem==ans){
                    if(strcmp(str[i],str[pos])<0)
                        pos=i;
                }
            }
            else{
                for(j=0;j<l1;j++){
                    for(k=0;k<l1;k++)
                        temp[k]=s[(j+k)%l1];
                    temp[k]='\0';
                    int tem=cal(temp,str[i],l1,l2);
                    if(tem<ans){
                        ans=tem;
                        pos=i;
                    }
                    else if(tem==ans){
                        if(strcmp(str[i],str[pos])<0)
                            pos=i;
                    }
                }
            }
        }
        printf("%s %d\n",str[pos],ans);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值