最长公共字符串

给出两个字符串,写一个函数找到最长公共子串,并返回其长度。


注意事项:

子串的字符应该连续的出现在原字符串中,这与子序列有所不同。


格式:


输入行输入两个字符串 A 和 B,最后输出最长公共子串的长度


样例输入


A = “ABCD”

B = “CBCE”


样例输出


2

动态规划算法即可。

用“ABDABC”和“ABEABC”做解题思路。直接先上动态规划表。

 "ABDABC
"0000000
A0100100
B0020020
E0000000
A0100100
B0020020
C0000003

横坐标为i(代表行),纵坐标为j(代表列)上面表格中可以看出

i=0,则由与是空字符串,则该行对应的每一列都是0

从i=1开始

1、如果第j列对应的字符与第i行对应的字符相等,则单元格(i,j)=(i-1,j-1)+1。为什么?因为在当前第i行与第j列相等的情况下,最长的公共字符串就是前面i-1行,j-1列最长的公共字符串加上当前的这一个公共字符。

2、如果第j列对应的字符与第i行对应的字符不等,则单元格(i,j)=0

从上表格中可以看出,公共字符串有多个,那么最长的公共字符串的最后一个字符对应的(i,j)值是可以找到的,由此往前(i-1,j-1)做回溯,就可以找到公共字符串。

代码如下:

package suanfa;

import java.util.HashMap;
import java.util.Map;

public class MaxLengthChars {

	public static void main(String[] args) {
		String str1 = "ABCERQQQQQTVERTYUIQRRRRRRRMNBTRASDG";
		String str2 = "ABCERQQQQQPVERTYUIQRRRRRRRADCDFEDC";
		Map<String,Object> map = compute(str1, str2);
		System.out.println("最长公共字符串长度为:"+map.get("maxLength"));
		System.out.println(getCommonChars((int[][])map.get("map"), str1, (int)map.get("I"),(int)map.get("J")));

	}


	/**
	 * 
	 * @param map
	 * @param str1
	 * @param i
	 * @param j
	 * @return
	 */
	public static String getCommonChars(int[][] map, String str1, int i, int j) {
		String res = "";
		while (map[i][j] != 1) {
			res = str1.substring(i - 1, i) + res;
			i--;
			j--;
		}
		return str1.substring(i - 1, i) + res;
	}

	/**
	 * 计算最长公共字符串
	 * 
	 * @param str1
	 * @param str2
	 * @return
	 */
	public static Map<String,Object> compute(String str1, String str2) {
		Map<String,Object> rmap = new HashMap<String,Object>();
		str1 = "\0" + str1;
		str2 = "\0" + str2;
		char[] arr1 = str1.toCharArray();
		char[] arr2 = str2.toCharArray();
		int maxLength = 0;

		int[][] map = new int[arr1.length][arr2.length];

		for (int i = 0; i < arr1.length; i++) {
			map[i][0] = 0;
		}

		for (int i = 0; i < arr2.length; i++) {
			map[0][i] = 0;
		}

		for (int i = 1; i < arr1.length; i++) {
			for (int j = 1; j < arr2.length; j++) {
				if (arr1[i] == arr2[j]) {
					if (arr1[i - 1] == arr2[j - 1]) {
						map[i][j] = map[i - 1][j - 1] + 1;
						if(maxLength < map[i][j]){
							maxLength = map[i][j];
							rmap.put("maxLength", map[i][j]);
							rmap.put("I", i);
							rmap.put("J", j);
						}
					} else {
						map[i][j] = 1;
					}
				} else {
					map[i][j] = 0;
				}
			}
		}
		rmap.put("map", map);
		return rmap;
	}


}

运行结果:

最长公共字符串长度为:15
VERTYUIQRRRRRRR

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值