编程之美3.3 计算两个字符串的相似度

      假如有两个字符串分别是:abcd,bbcd,那么,这两个字符串不相同的字符个数是1,即第一个字符时不相同的,定义字符串的相似度为 1 / (x + 1),其中,x 就是不相同的字符个数。

      我们可以有三种方法比较两个字符串中不相同字符的个数:

      1.去掉第一个字符串中不相同的那个字符,并同时再去比较下一个字符

      2.去掉第二个字符串中不相同的那个字符,并同时再去比较下一个字符

      3.同时去掉字符串中不相同的那个字符,并同时再去比较下一个字符

      之后,我们需要把不相同的字符个数加 1 ,最后,我们只需要取得三种方法中值最小的那个即可。

      很容易发现,依次比较字符是否相同时时递归的操作,所以,这道题目解法如下:

      函数声明:

/*3.3 计算两个字符串的相似度*/
int DutCalculateStringDistance(std :: string&, std :: string&);
int DutCalculateStringDistance(std :: string&, int, int, std :: string&, int, int);

      源代码:

int DutCalculateStringDistance(string& s1, int begin1, int end1, string& s2, int begin2, int end2)
{
	if (begin1 > end1)
	{
		if (begin2 > end2)
			return 0;
		else
			return end2 - begin2 + 1;
	}

	if (begin2 > end2)
	{
		if (begin1 > end1)
			return 0;
		else
			return end1 - begin1 + 1;
	}

	if (s1[begin1] == s2[begin2])
		return DutCalculateStringDistance(s1, begin1 + 1, end1, s2, begin2 + 1, end2);
	else
	{
		/*计算各个不同办法的相似度*/
		int t1 = DutCalculateStringDistance(s1, begin1 + 1, end1, s2, begin2, end2);
		int t2 = DutCalculateStringDistance(s1, begin1, end1, s2, begin2 + 1, end2);
		int t3 = DutCalculateStringDistance(s1, begin1 + 1, end1, s2, begin2 + 1, end2);

		/*取一个最小的相似度*/
		return DutMin<int>(t1, t2, t3) + 1;
	}
}

int DutCalculateStringDistance(string& s1, string& s2)
{
	return DutCalculateStringDistance(s1, 0, (int)s1.length() - 1, s2, 0, (int)s2.length() - 1);
}

      代码中用到的模板函数:

template <typename T>
T DutMin(T data1, T data2)
{
	return data1 < data2 ? data1 : data2;
}
template <typename T>
T DutMin(T data1, T data2, T data3)
{
	return DutMin<T>(DutMin<T>(data1, data2), data3);
}


时间: 2024-11-05 17:32:20

编程之美3.3 计算两个字符串的相似度的相关文章

比较字符串总结:如果计算两个字符串的相似度或者距离

有关字符串相关比较问题,一般处理方法都选择动态规划处理方法.或者是单个循环,或者是多个循环:dp 遇到这种两个串的问题,很容易想到DP.但是这道题的递推关系不明显.可以先尝试做一个二维的表int[][] dp,用来记录匹配子序列的个数(以S="rabbbit",T = "rabbit"为例): r a b b b i t 1 1 1 1 1 1 1 1 r 0 1 1 1 1 1 1 1 a 0 0 1 1 1 1 1 1 b 0 0 0 1 2 3 3 3 b 0

C#通过编辑距离计算两个字符串的相似度的代码

将开发过程中较好的一些代码段备份一下,下面的代码是关于C#通过编辑距离计算两个字符串的相似度的代码,应该能对码农们有些帮助. using System; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Levenshtein { public delegate void AnalyzerCompletedHander(double sim); public class Levenshtei

编程之美3.3—计算字符串的相似度

题目: 许多程序会大量使用字符串.对于不同的字符串,我们希望能够有办法判断其相似程序.我们定义一套操作方法来把两个不相同的字符串变得相同,具体的操作方法为: 1.修改一个字符(如把"a"替换为"b"); 2.增加一个字符(如把"abdd"变为"aebdd"); 3.删除一个字符(如把"travelling"变为"traveling"); 比如,对于"abcdefg"和

计算两个字符串的相似度---动态规划实现

问题描述:把两个字符串变成相同的基本操作定义如下:1.     修改一个字符(如把 a 变成 b)2.     增加一个字符 (如 abed 变成 abedd)3.     删除一个字符(如 jackbllog 变成 jackblog)针对于 jackbllog到jackblog 只需要删除一个或增加一个 l 就可以把两个字符串变为相同.把这种操作需要的次数定义为两个字符串的距离 L, 则相似度定义为1/(L+1) 即距离加一的倒数.那么jackbllog和jackblog的相似度为 1/1+1

编程之美3.6—判断两个链表是否相交

解法一: 判断第一个链表的每个节点是否在第二个链表中,O(M*N): 解法二: 对第一个链表的节点地址hash排序,建立hash表,然后对第二个链表的每个节点的地址查询hash表,如出现,相交 时间复杂度O(M+N),空间复杂度O(M). 解法三: 把第二个链表接在第一个链表后面,得到的链表有环,相交,否则,不相交.' 第二个链表的表头一定在环上,只需从第二个链表开始遍历 时间复杂度O(N),常数空间 解法四: 如果两个没有环的链表相交于某一节点,那么在这个节点之后的所有节点都是两个链表共有的.

编程之美2.13 子数组最大乘积

问题描述: 给定一个长度为N的整数数组,只允许用乘法,不能用除法,计算任意(N-1)个数的组合乘积中最大的一组,并写出算法的时间复杂度. 解法: 1.暴力解法------O(n^2) 2.前后缀法------O(n) 3.统计法--------O(n) 具体思路和代码: 1.暴力解法: 思路:利用两层循环,依次删掉一个,其余的做乘法,计算出最大的. 代码: 1 int s1(int A[], int n) 2 { 3 int s = 1; 4 int max; 5 for(int i = 1;

编程之美2.17之数组循环移位

题目描述:设计一个算法,把一个含有N个元素的数组循环右移K位,要求算法的时间复杂度位O(Log2N),且只允许使用两个附加变量. 什么意思呢,就是说如果输入序列为:abcd1234,右移2位即变为34abcd12.唯一的要求就是使用两个附加变量. 其实这道题编程珠玑上面也出现过,书中给出的一种符合题意的解法是巧妙地进行翻转.以把abcd1234右移4位为例: 第一步:翻转1234,abcd1234---->abcd4321 第二步:翻转abcd,abcd4321---->dcba4321 第三

编程之美2.3: 寻找发帖水王

题目:传说,Tango有一大"水王",他不但喜欢发帖,还会回复其他ID发的帖子,发帖数目超过帖子总数的一半,如果你有一个当前论坛上所有帖子的列表,其中帖子作者的ID也在表中,你能快速找到这个传说中的Tango水王吗? 解题思路:由于水王的发帖数目超过一半,当每次删除两个不同ID的帖子时,水王占得帖子数目仍然大于剩下帖子的一半,重复整个过程,将ID列表中的ID总数降低,转化为更小的问题,从而得到最后水王的ID. #include <iostream> #include <

编程之美2.1 求二进制中1的个数

最近一段的时间,一直在看编程之美之类的算法书籍,刚开始看编程之美,感觉到难度太大,有时候也不愿意去翻动这本书,不过,经过一段时间的修炼,我也彻底的喜欢上这本书了, 书中的算法涉及到很多方面,树,链表,位运算,数组,hash表应用等等. 由于最近事情也忙得差不多了,我重新写了一遍编程之美中的算法,在这里记录下来,以便以后阅读方便. 第一道题从2.1写起,这道题目难度不是很大,首先,给出这个题目的函数声明: /*2.1 求二进制中1的个数*/ int DutCountOf1InBin_1(unsig