zoukankan      html  css  js  c++  java
  • 算法题8 动态规划之字符串相似度

    题目

      题目来源:《编程之美》

      把两个字符串变成相同的基本操作定义如下:

      1. 修改一个字符(如把 a 变成 b)
      2. 增加一个字符 (如 abed 变成 abedd)
      3. 删除一个字符(如 jeddon 变成 jedon)
      针对于 jeddon到jedon 只需要删除一个或增加一个 d 就可以把两个字符串变为相同。把这种操作需要的次数定义为两个字符串的距离 L, 则相似度定义为1/(L+1) 即距离加一的倒数。那么jeddon和jedon的相似度为 1/1+1=1/2=0.5 也就是所两个字符串的相似度是 0.5。
      给定任意两个字符串,你是否写出一个是否来计算出它们的相识度。

    分析

      这是一个多阶段决策问题,每个阶段的决策都和前面子问题的最优决策相关,可以用动态规划来做。

      对于字符串str1 和str2,长度分别为m,n,设d[i,j]为str1的第[1—i]字符和str2的第[1—j]个字符之间的距离,

      如果str1[i]=str2[j],则d[i,j]=d[i-1,j-1];

      如果str1[i]和str2[j]替换一个字符,str1[0-i]和str2[0-j]就相同,比如"student"和"studens",则d[i,j]=d[i-1,j-1]+1;

      如果str1[i]增加一个字符,str1[0-i]和str2[0-j]就相同,比如"student"和"students",则d[i,j]=d[i,j-1]+1;

      如果str1[i]删除一个字符,str1[0-i]和str2[0-j]就相同,比如"students"和"student",则d[i,j]=d[i-1,j]+1;

      由此可以得到关系式:

          d[i,0]=i

          d[0,j]=j;

          d[i,j]=min{d[i-1,j-1]+1,d[i,j-1]+1,d[i-1,j]+1}

      算法时间复杂度为O(m*n),空间复杂度为O(m*n)

    代码

    int SimilarityDegreeOfStrs(char* str1,char* str2)
    {
    	 int len1=strlen(str1);
    	 int len2=strlen(str2);
    
    	 int **d=new int*[len1+1];
    	 for (int i=0;i<=len1;i++)
    	 {
    		 d[i]=new int[len2+1]();
    	 }
    
    	 for (int i=0;i<=len1;i++)
    	 {
    		 d[i][0]=i;
    	 }
    	 for (int j=0;j<=len2;j++)
    	 {
    		 d[0][j]=j;
    	 }
    
    	 for (int i=1;i<=len1;i++)
    	 {
    		 for (int j=1;j<=len2;j++)
    		 {
    			 if (str1[i-1]==str2[j-1])
    			 {
    				 d[i][j]=d[i-1][j-1];
    			 }else
    			 {
    				 int repl=d[i-1][j-1]+1;
    				 int add=d[i][j-1]+1;
    				 int del=d[i-1][j]+1;
    				 d[i][j]=MIN(MIN(repl,add),del);
    			 }
    		 }
    	 }
    
    	 int similarity=d[len1][len2]/(d[len1][len2]+1);
    
    	 //free
    	 for (int i=0;i<=len1;i++)
    	 {
    		 delete[] d[i];
    	 }
    	 delete[] d;
    
    	 return similarity;
    }
    

      

  • 相关阅读:
    js:值类型/引用类型/内存回收/函数传值
    JS学习计划
    起点
    哈夫曼压缩/解压缩(控制台,C++)
    二维数组作为函数参数传递(C++)
    二级指针和指针引用函数传参(C++)
    学生管理系统(C++,控制台,文件读取,姓名排序)
    C++的getline()和get()函数
    二叉排序树节点的删除(C++,算法导论),前中后序遍历(递归/非递归,栈实现),按层次遍历(队列实现)
    QT程序打包成EXE
  • 原文地址:https://www.cnblogs.com/wangzaizhen/p/5167630.html
Copyright © 2011-2022 走看看