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

该博客探讨如何衡量两个字符串的相似度,通过修改、增加或删除字符实现。作者提出了一种递归方法,并注意到递归中可能存在的重复计算问题,随后介绍了使用动态规划来优化这一过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

对于不同的字符串,我们希望能够有办法判断其相似程度,我们定义了一套操作方法来把两个不相同的字符串变得相同,具体的操作办法为:

1. 修改一个字符,如把'a'替换为'b'

2. 增加一个字符,如把‘abdd'变成’aebdd'

3. 删除一个字符,如把'travelling'变成‘traveling'

两个字符串的相似度即把一个字符串变成另一个字符串的步骤的导数。

解法:

采用递归方法,逐一对比字符串,同时对字符串的操作归类为三种情况

import java.util.*;
public class StringDistance
{
	public static void main(String[] args)
	{
		System.out.println("input Str1:");
		Scanner s = new Scanner(System.in);
		String s1 = s.next();
		char[] c1 = new char[s1.length()];
		c1 = s1.toCharArray();
		System.out.println("input Str2:");
		String s2 = s.next();
		char[] c2 = new char[s2.length()];
		c2 = s2.toCharArray();
		int distance = calculateStringDistance(c1,0,s1.length()-1,c2,0,s2.length()-1);
		System.out.println(s1+" and "+s2+" distance is:"+distance);
	}
	public static int calculateStringDistance(char[] strA,int pABegin,int pAEnd,char[] strB,int pBBegin,int pBEnd)
	{
		if(pABegin>pAEnd)
		{
			if(pBBegin>pBEnd)
				return 0;
			else
				return pBEnd-pBBegin+1;
		}
		if(pBBegin>pBEnd)
		{
			if(pABegin>pAEnd)
				return 0;
			else
				return pAEnd-pABegin+1;
		}
		if(strA[pABegin]==strB[pBBegin])
		{
			return calculateStringDistance(strA,pABegin+1,pAEnd,strB,pBBegin+1,pBEnd);
		}
		else
		{
			
			int t1 = calculateStringDistance(strA,pABegin+1,pAEnd,strB,pBBegin,pBEnd);
			int t2 = calculateStringDistance(strA,pABegin,pAEnd,strB,pBBegin+1,pBEnd);
			int t3 = calculateStringDistance(strA,pABegin+1,pAEnd,strB,pBBegin+1,pBEnd);
			return Math.min(t1,t2)>Math.min(t2,t3)?Math.min(t1,t2)?Math.min(t2,t3);
		}
	} 
	public static int minValue(int t1, int t2, int t3)
	{
		int min = t1;
		if(t1>t2)
		{
			min = t2;
			if(t2>t3)
			min = t3;
		}
		else
		{
			if(t1>t3)
				min = t3;
		}
		return min;
	}
}

上面的程序解决了这个问题,但是在递归过程中,有可能会出现重复计算的情况,因此下面的程序对此进行优化,即动态规划

import java.util.*;
public class StringDistanceUpdate
{
	public static void main(String[] args)
	{
		System.out.println("input strA:");
		Scanner s = new Scanner(System.in);
		String strA = s.next();
		System.out.println("input strB:");
		String strB = s.next();
		int i = 0;
		i = EditDistance(strA,strB);
		System.out.println(strA+" and "+strB+" distance is:"+i);
	}
	public static int EditDistance(String source,String target)
	{
		char[] s = source.toCharArray();
		char[] t = target.toCharArray();
		int slen = source.length();
		int tlen = target.length();
		int[][] d = new int[slen+1][tlen+1];
		for(int i=0;i<slen;i++)
			d[i][0] = i;
		for(int i=0;i<tlen;i++)
			d[0][i] = i;
		for(int i=1;i<=slen;i++)
		{
			for(int j=1;j<=tlen;j++)
			{
				if(s[i-1]==t[j-1])
				{
					d[i][j] = d[i-1][j-1];
				}
				else
				{
					int insert = d[i][j-1]+1;
					int del = d[i-1][j]+1;
					int update = d[i-1][j-1]+1;
					d[i][j] = Math.min(insert,del)>Math.min(del,update)?Math.min(insert,del):Math.min(del,update);
				}
			}
		}
		return d[slen][tlen];
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值