zoukankan      html  css  js  c++  java
  • POJ2146 Confusing Login Names [最小字符串编辑距离]

      给出一个字符串S1和S2,可以对S1进行添加字符(insert),删除字符(delete),替换字符(replace),交换相邻字符(swap)四种操作,问是否能在dis步骤内将S1转换成S2。

      用d[i][j]表示将S1[1..i]转化为S2[1..j]的最小步数。

      这几种操作可以表示为:添加d[i][j]=d[i][j-1]+1,删除d[i][j]=d[i-1][j]+1,替换d[i][j]=d[i-1][j-1]+1,交换d[i][j]=d[i-2][j-2]+1(条件为s1[i-1]==s2[j]&s1[i]==s2[j-1])。

      但是仅考虑到这些还是过不了这道题的,因为交换操作可以减少其它操作的步数,比如说S1="ca",S2="abc",可以通过先swap(c,a),然后在中间insert(b),这样2步就可以由S1转化到S2,也就是说d[i][j]=d[i-2][j-3]+2。当S1="abc",S2="ca"时,可以先delete(b),然后再swap(a,c)变成2,也就是说d[i][j]=d[i-3][j-2]+2。实质是通过insert和delete辅助swap完成了不相邻的两个数的交换。这题中的dis范围是2,最多也只能操作两次,一开始没注意这个条件,还想了好久。。。

      最后的DP方程大概就是,具体的条件看代码就清楚了。

    #include <cstdio>
    #include <string.h>
    #include <algorithm>
    #define INF 0x3fffffff
    using namespace std;
    struct cstr{
        char s[22];
        bool operator <(const cstr& c)const{
            return strcmp(s,c.s)<0;
        }
    }st[205];
    int n,dis,d[20][20];
    int dp(char *s1,char *s2){
        int l1=strlen(s1),l2=strlen(s2);
        memset(d,0,sizeof d);
        for(int i=1;i<=l2;i++)d[0][i]=i;
        for(int i=1;i<=l1;i++)d[i][0]=i;
        for(int i=1;i<=l1;i++){
            for(int j=1;j<=l2;j++){
                d[i][j]=INF;
                if(s1[i-1]==s2[j-1]){
                    d[i][j]=d[i-1][j-1];
                }else{
                    d[i][j]=min(d[i][j-1],min(d[i-1][j],d[i-1][j-1]))+1;
                }
                if(i>=2&&j>=2&&s1[i-2]==s2[j-1]&&s1[i-1]==s2[j-2]){
                    d[i][j]=min(d[i][j],d[i-2][j-2]+1);
                }
                if(i>=2&&j>=3&&s1[i-2]==s2[j-1]&&s1[i-1]==s2[j-3]){
                    d[i][j]=min(d[i][j],d[i-2][j-3]+2);
                }
                if(i>=3&&j>=2&&s1[i-1]==s2[j-2]&&s1[i-3]==s2[j-1]){
                    d[i][j]=min(d[i][j],d[i-3][j-2]+2);
                }
            }
        }
        return d[l1][l2];
    }
    
    int main(){
       // freopen("test.in","r",stdin);
        while(scanf("%d",&n),n){
            scanf("%d",&dis);
            for(int i=0;i<n;i++)scanf("%s",st[i].s);
            sort(st,st+n);
            int tot=0;
            for(int i=0;i<n;i++){
                for(int j=i+1;j<n;j++){
                    int x=dp(st[i].s,st[j].s);
                    if(x<=dis){
                        tot++;
                        printf("%s,%s\n",st[i].s,st[j].s);
                    }
                }
            }
            printf("%d\n",tot);
        }
        return 0;
    }
  • 相关阅读:
    NHibernate中多表(对象)间的查询
    将datagrid数据导到excel的一个问题
    win2003<IIS6>部署.net 4.0<asp.net 4>
    C# 单元测试
    office2010 word发布博客 博客园
    语义化的HTML首先要强调HTML结构
    SQL Server 2005 安装(各种错误)
    SWFUpload V2.2.0 说明文档
    SQL Server 复制, 集群
    高亮插件测试
  • 原文地址:https://www.cnblogs.com/swm8023/p/2619946.html
Copyright © 2011-2022 走看看