博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DP系列-最长公共子串和最长公共子序列总结
阅读量:3571 次
发布时间:2019-05-20

本文共 2896 字,大约阅读时间需要 9 分钟。

知识点:

最长公共子串问题是寻找两个或多个已知字符串最长的子串。

此问题与最长公共子序列问题的区别在于子序列不必是连续的,而子串却必须是。

例如:

str1="123ABCD4567"      str2 = "ABE12345D6"

最长公共子串是:123

最长公共子序列是:123456

1.最长公共子串

题目描述:

 计算两个字符串的最大公共字串的长度,字符不区分大小写。

 输入描述:输入两个字符串,分两行输入。

 输出描述:输出一个整数。

 示例:

 输入:

 asdfas

 werasdfaswer

输出:6

 

思路:

dp[i][j] -- 表示以str1[i]和str2[j]为结尾的最长公共子串

当str1[i] == str2[j]时,dp[i][j] = dp[i-1][j-1] + 1;

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

最优解为max(dp[i][j]),其中0<=i<len1, 0<=j<len2;

实现:

import java.util.Scanner;public class LongestCommonSubString {	 public static void main(String[] args) {	        Scanner sc = new Scanner(System.in);	        while (sc.hasNextLine()) {	            String str1 = sc.nextLine().toLowerCase();	            String str2 = sc.nextLine().toLowerCase();	            System.out.println(getCommonStrLength(str1, str2));	        }	    }	 	    private static int getCommonStrLength(String str1, String str2) {	        int len1 = str1.length();	        int len2 = str2.length();	        int[][] dp = new int[len1 + 1][len2 + 1];	        for (int i = 1; i <= len1; i++) {	            for (int j = 1; j <= len2; j++) {	                if (str1.charAt(i - 1) == str2.charAt(j - 1)) {	                    dp[i][j] = dp[i - 1][j - 1] + 1;	                } else {	                    dp[i][j] = 0;	                }	            }	        }	        int max = 0;	        for (int i = 0; i <= len1; i++) {	            for (int j = 0; j <= len2; j++) {	                if (dp[i][j] > max) {	                    max = dp[i][j];	                }	            }	        }	        return max;	    }}

2.最长公共子序列

LCS是Longest Common Subsequence的缩写,即最长公共子序列。一个序列,如果是两个或多个已知序列的子序列,且是所有子序列中最长的,则为最长公共子序列。

比如,对于char x[]="aabcd";有顺序且相互相邻的aabc是其子序列,有顺序但是不相邻的abc也是其公共子序列。即,只要得出序列中各个元素属于所给出的数列,就是子序列。再加上char y[]="12abcabcd";对比出才可以得出最长公共子序列abcd。

 

题目描述:

计算两个字符串的最长公共子序列的长度,字符不区分大小写。

 输入描述:输入两个字符串,分两行输入。

 输出描述:输出一个整数。

示例:

 输入:

ABCBDAB

BDCABA
输出:4

思路:

公式推导参见

dp[i][j] 表示子串A[0...i](数组长度为n)和子串B[0...j](数组长度为m)的最长公共子序列

当A[i] == B[j]时,dp[i][j] = dp[i-1][j-1] + 1;

否则,dp[i][j] = max(dp[i-1][j], dp[i][j-1]);

最优解为dp[n-1][m-1];

实现:

import java.util.Scanner;public class LongestCommonSubSeq {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        while (sc.hasNextLine()) {            String str1 = sc.nextLine().toLowerCase();            String str2 = sc.nextLine().toLowerCase();            System.out.println(findLCS(str1, str1.length(), str2, str2.length()));        }    }    public static int findLCS(String A, int n, String B, int m) {        int[][] dp = new int[n + 1][m + 1];        for (int i = 1; i <= n; i++) {            for (int j = 1; j <= m; j++) {                if (A.charAt(i - 1) == B.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[n][m];    }}

 

参考:

根据该博客写的代码并做了总计和修改。

转载地址:http://jmdgj.baihongyu.com/

你可能感兴趣的文章
代码审计 N4 常见危险函数和特殊函数(一)
查看>>
MySQL笔记
查看>>
计算机运算方法之(原码 补码 反码 移码)
查看>>
计算机组成原理之(二进制与十进制互相转换,数的定点表示与浮点数表示)例题:设浮点数字长16位,其中阶码5位(含有1位阶符),尾数11位(含有1位数符)
查看>>
选择排序(java代码实现)
查看>>
插入排序
查看>>
哈夫曼树java代码实现
查看>>
快速排序
查看>>
vue路由高亮的两种方式
查看>>
vue router 报错: Uncaught (in promise) NavigationDuplicated {_name:""NavigationDuplicated"... 的解决方法
查看>>
vue跳转页面的两种方式
查看>>
存储器题目解析(持续更新中....)
查看>>
存储器知识要点
查看>>
Cache模拟器的实现
查看>>
设计模式七大原则
查看>>
SpringBoot入门(二)场景启动器
查看>>
SpringBoot入门--自动配置
查看>>
自动配置原理
查看>>
TCP协议
查看>>
关于Linux系统使用遇到的问题-1:vi 打开只读(readonly)文件如何退出保存?
查看>>