目录
题目:
输入描述:
输出描述:
示例1
输入
输出
备注:
思路分析-未空间压缩:
思路分析-空间压缩:
代码展示:
题目:
给定两个字符串str1和str2,输出两个字符串的最长公共子串,如果最长公共子串为空,输出-1。
输入描述:
输入包括两行,第一行代表字符串srr1,第二行代表字符串str2。 1 ≤ length( str1), length(str2) ≤ 5000
输出描述:
输出包括一行,代表最长公共子串。
示例1
输入
1AB2345CD 12345EF
输出
2345
备注:
时间复杂度O(N^2),额外空间复杂度O(1)。(n可以为其中任意一个字符串长度)
思路分析-未空间压缩:
- 申请一个二维表dp[s2.length()][s1.length()]
- 行代表str2,索引i代表字符串当前字符str2[i]
- 列代表str1,索引j代表字符串当前字符str1[j]
- dp[i][j]代表 以str2[i]结尾的字串str2` 与 以str1[j]结尾的字串str1` 的最长公共字串
- 因为str1与str2的最长公共字串一定会以某个i某个j结尾,所以dp[i][j]中的最大值就是公共字串的长度
- 然后将最大长度处的索引向前推,就可以得到最长公共字串
- 为什么会这样定义,因为子串要求要连续,所以当以i,j结尾且str2[i] == str1[j]时,如果上一个是连续,则当前也一定连续
- 初始化
- 首行如果相等,则dp[i][j] = 1 否则dp[i][j] = 0
- 不用初始化首列,因为dp只依赖于左上角
- 其余点:
- 如果str2[i] == str1[j]则dp[i][j] = dp[i-1][j-1] + 1
- 否则dp[i][j] = 0
- 在填写dp时,更新最大值max,与最大值对应的i的索引值pos
- 根据最大长度与索引值还原最长子串
思路分析-空间压缩:
- 因为dp只依赖于左上角,所以不需要再申请一个二维表
- 只需要几个变量,从右上角点开始,划“捺”
- 定义出发点,出发点一开始时(0,m-1)
- 出发点向左移动,遇到边界后向下移动
代码展示:
import java.io.*;
public class Main{
public static void main(String[] args)throws IOException{
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
String s1 = read.readLine();
String s2 = read.readLine();
int n = s2.length();
int m = s1.length();
int col = m-1;//出发点的列
int row = 0;//出发点的行
int max=0;//最大长度
int pos = -1;//索引
while(col!=0 || row < n){
int i = row;
int j = col;
int len = 0;
while(i<n && j<m){//划“捺”
if(s1.charAt(j) == s2.charAt(i)){
len++;
if(len>max){
max = len;
pos = i;
}
}else{
len=0;
}
i++;
j++;
}
if(col == 0){//出发点先左移到边界,再下移
row++;
}else{
col--;
}
}
String str = s2.substring(pos-max+1,pos+1);
if(str.length()==0){
str = "-1";
}
System.out.println(str);
}
}
相关文章
暂无评论...