编辑距离和最长公共子串

编辑距离和最长公共子串问题都是经典的DP问题,首先来看看编辑距离问题:

问题描述

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

You have the following 3 operations permitted on a word:

a) Insert a character
b) Delete a character
c) Replace a character

解决思路

经典的动态规划题,建立一个二维的数组dp[][]记录两个字符串s1和s2子串的最短编辑距离,递推公式如下:

(1) 当s1.charAt(i) == s2.charAt(j)时,dp[i][j] = dp[i - 1][j - 1];

(2) 其他时,dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i][j - 1], dp[i - 1][j]));

初始化条件为:

dp[i][0] = i, dp[0][j] = j;

代码

	public int getMinEditLen(String s1, String s2) {
		if (s1 == null && s2 == null) {
			return 0;
		}

		if (s1.length() == 0) {
			return s2.length();
		}
		if (s2.length() == 0) {
			return s1.length();
		}

		int len1 = s1.length();
		int len2 = s2.length();

		int[][] dp = new int[len1 + 1][len2 + 1];
		// initialize
		for (int i = 0; i < dp.length; i++) {
			dp[i][0] = i;
		}
		for (int j = 0; j < dp[0].length; j++) {
			dp[0][j] = j;
		}

		for (int i = 1; i < dp.length; i++) {
			for (int j = 1; j < dp[0].length; j++) {
				if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
					dp[i][j] = dp[i - 1][j - 1];
				} else {
					dp[i][j] = Math.min(dp[i - 1][j - 1],
							Math.min(dp[i - 1][j], dp[i][j - 1])) + 1;
				}
			}
		}

		return dp[len1][len2];
	}

 容易写错的地方

if (word1.substring(0, i).equals(word2.substring(0, j))) {
        dp[i][j] = 0;
}

最长公共子串问题

问题描述

子字符串的定义和子序列的定义类似,但要求是连续分布在其他字符串中。比如输入两个字符串BDCABA和ABCBDAB的最长公共字符串有BD和AB,它们的长度都是2。

解决思路

(1) 递归;

(2) dp;

代码

	// rec
	private static int getLCS(String s1, String s2) {
		if (s1.length() == 0 || s2.length() == 0) {
			return 0;
		}

		int len1 = s1.length();
		int len2 = s2.length();

		if (s1.charAt(len1 - 1) == s2.charAt(len2 - 1)) {
			return getLCS(s1.substring(0, len1 - 1), s2.substring(0, len2 - 1)) + 1;
		}

		return Math.max(
				getLCS(s1.substring(0, len1), s2.substring(0, len2 - 1)),
				getLCS(s1.substring(0, len1 - 1), s2.substring(0, len2)));
	}
	// dp
	private static int getLCS(String s1, String s2) {
		if (s1.length() == 0 || s2.length() == 0) {
			return 0;
		}

		int len1 = s1.length();
		int len2 = s2.length();

		int[][] dp = new int[len1 + 1][len2 + 1];
		for (int i = 1; i < dp.length; i++) {
			for (int j = 1; j < dp[0].length; j++) {
				if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
					dp[i][j] = dp[i - 1][j - 1] + 1;
				} else {
					dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
				}
			}
		}

		return dp[len1][len2];
	}
时间: 2024-08-06 07:54:03

编辑距离和最长公共子串的相关文章

最长递增子序列 &amp;&amp; 最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离

http://www.cppblog.com/mysileng/archive/2012/11/30/195841.html 最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增子序列. 设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为: dp[i] = max{dp[j]+1}, 1<=j<i,a[j]<a[i]. 这样简单的复杂度为O(n^2),其实还有更好的方

最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离

http://www.cnblogs.com/zhangchaoyang/articles/2012070.html 把一个问题转换为若干个规模更小的子问题,并且都借助于一个二维矩阵来实现计算. 约定:字符串S去掉最后一个字符T后为S',T1和T2分别是S1和S2的最后一个字符. 则dist(S1,S2)是下列4个值的最小者: 1.dist(S1',S2')--当T1==T2 2.1+dist(S1',S2)--当T1!=T2,并且删除S1的最后一个字符T1 3.1+dist(S1,S2')--

动态规划算法之:最长公共子序列 & 最长公共子串(LCS)

1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. 2.最长公共子串 其实这是一个序贯决策问题,可以用动态规划来求解.我们采用一个二维矩阵来记录中间的结果.这个二维矩阵怎么构造呢?直接举个例子吧:"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是"ba"或"ab") b a b c 0 0 0 a 0 1

《算法导论》读书笔记之动态规划—最长公共子序列 &amp; 最长公共子串(LCS)

From:http://my.oschina.net/leejun2005/blog/117167 1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. 2.最长公共子串 其实这是一个序贯决策问题,可以用动态规划来求解.我们采用一个二维矩阵来记录中间的结果.这个二维矩阵怎么构造呢?直接举个例子吧:"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是

最长公共子串、最长公共子序列的Java实现与NLP应用

前言以前HanLP使用"最短编辑距离"来做推荐器,效果有待提高,主要缺点是根据拼音序列的编辑距离推荐的时候,同音字交错很常见,而编辑距离却不那么大.这时我就在寻求一种补充的评分算法,去评判两个句子在拼音这一维度上的相似程度.区别最长公共子串(Longest Common Substring)指的是两个字符串中的最长公共子串,要求子串一定连续.最长公共子序列(Longest Common Substring)指的是两个字符串中的最长公共子串,不要求子串连续.求解两者的求解与编辑距离一样,

最长公共子串

(连续) - 阿里笔试[分析+编码] 题目描述:给定一个query和一个text,均由小写字母组成.要求在text中找出以同样的顺序连续出现在query中的最长连续字母序列的长度.例如,query为“acbac”,text为“acaccbabb”,那么text中的“cba”为最长的连续出现在query中的字母序列,因此,返回结果应该为其长度3.请注意程序效率. [思路]用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0.然后求出对角线最长的1序列,其对应的位置

一天一道算法题(5)---最长公共子串

题目 给定两个字符串str1和str2,返回两个字符串的最长公共子串.例如:str1="1AB2345CD",str2="12345EF",公共子串是"2345" 解析 最长公共子串和最长公共子序列的区别是,子串是连续的,子序列是不连续的. 首先还是要生成动态规划表.生成大小为M*N的矩阵dp.dp[i][j]的含义是,在必须把str1[i]和str2[j]当作公共子串最后一个字符的情况下,公共子串最长能有多长.比如,str1="A12

3160 最长公共子串

3160 最长公共子串 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 给出两个由小写字母组成的字符串,求它们的最长公共子串的长度. 输入描述 Input Description 读入两个字符串 输出描述 Output Description 输出最长公共子串的长度 样例输入 Sample Input yeshowmuchiloveyoumydearmotherreallyicannotbelieveityeaphow

[URAL-1517][求两个字符串的最长公共子串]

Freedom of Choice URAL - 1517 Background Before Albanian people could bear with the freedom of speech (this story is fully described in the problem "Freedom of speech"), another freedom - the freedom of choice - came down on them. In the near fu