学习目标:
目标:熟练运用Java所学知识
学习内容:
本文内容:使用java解决 查找两个字符串a,b中的最长公共子串
题目描述
查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个。
注:子串的定义:将一个字符串删去前缀和后缀(也可以不删)形成的字符串。请和“子序列”的概念分开!
本题含有多组输入数据!
输入描述:
输入两个字符串
输出描述:
返回重复出现的字符
示例1
输入
abcdefghijklmnop
abcsafjklmnopqrstuvw
输出
jklmnop
解题思路
动态规划题目
str1=abcdefghijklmnop
str2=abcsafjklmnopqrstuvw
c1[] c2[]分别是str1,str2对应的字符数组
状态:
c1[ i ] :表示str1中以第i个字符结尾的字符串
c2[ j ]:表示 str2 中以第 j 个字符结尾的字符串
dp[i][j]:表示以str1中以第 i-1 个字符结尾的字符串和 str2 中以第 j-1 个字符结尾的字符串的最长公共子串的长度
比如dp[2][3] 表示 str1 中的 ab 和 str2 中的 abc 最长公共子串是ab
递推关系:
初始化:
注意:
使用两个变量:maxLen记录最大长度,end记录最大长度的结尾字符位置
因为题目要求最大公共子序列若有多个,输出在较短串中最先出现的那个。所以我们记录最大长度end记录的是较短字符串中的位置
实现代码
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
String str1=sc.next();
String str2=sc.next();
if(str1.length()>str2.length()){
//是Str1 始终是较短的字符串,方便记录
String temp=str1;
str1=str2;
str2=temp;
}
char[] c1=str1.toCharArray();
char[] c2=str2.toCharArray();
int[][] dp =new int[c1.length+1][c2.length+1];
for(int i=0;i<=c1.length;i++){
//初始化第一列
dp[i][0]=0;
}
for(int j=0;j<=c2.length;j++){
//初始化第一行
dp[0][j]=0;
}
int end=0;//记录最长公共子串的结束位置
int maxLen=0;//记录最长公共子串的长度
for(int i=1;i<=c1.length;i++){
for(int j=1;j<c2.length;j++){
if(c1[i-1]==c2[j-1]){
//当c1[i-1]==c2[j-1]时,dp[i][j]=dp[i-1][j-1]+1
dp[i][j]=dp[i-1][j-1]+1;
if(dp[i][j]>maxLen){
maxLen=dp[i][j];
end=i;
}
}
}
}
System.out.println(str1.substring(end-maxLen,end));
}
}
}