HJ75 公共子串计算
描述
对于给定的两个字符串s和t,你需要找出它们的最长公共子串的长度。
子串为从原字符串中,连续的选择一段字符(可以全选、可以不选)得到的新字符串。
如果字符串 α 的一个子串 a'与字符串b的一个子串b 完全相等,那么子串 α',b'是字符串a,b的一个公共子串。
输入描述:
第一行输入一个长度为 1 <= len(s)<= 150、仅由小写字母组成的字符串 s。
第二行输入一个长度为 1 <= len(t)<= 150、仅由小写字母组成的字符串 t。
输出描述:
输出一个整数,代表s和t的最长公共子串的长度。
示例1
输入:
awaabb
aawbb
输出:
2
说明:在这个样例中,"aa" 和 "bb" 都是 s 和 t 的最长公共子串。
示例2
输入:
asdfas
werasdfaswer
输出:
6
以下是把代码喂给deepseek后对 最长公共子串 代码的通俗易懂解释,结合生活中的比喻帮助理解:
1. 问题场景
假设你有两个字符串:
- 字符串1:
"abcdefg"
- 字符串2:
"zbcdf"
你想找到它们最长的 连续相同部分 (子串)。比如它们的共同子串是 "bcd"
,长度为 3。
2. 动态规划思想
我们用一个 表格 (二维数组 dp
)来记录每一步的"最长连续相同部分长度"。
表格定义
dp[i][j]
表示:以字符串1的第i
个字符 和 字符串2的第j
个字符 结尾 的最长公共子串长度。
例如:
dp[3][2]
表示以字符串1的第3个字符(比如c
)和字符串2的第2个字符(比如b
)结尾的最长公共子串长度。
3. 填表规则
(1) 当前字符匹配
如果字符串1的第 i
个字符和字符串2的第 j
个字符相同:
- 相当于连续相同部分多了一个字符,所以当前长度 = 左上角的值 + 1。
- 公式 :
dp[i][j] = dp[i-1][j-1] + 1
(比如之前的连续相同部分是"bc"
,现在多了d
,变成"bcd"
)
(2) 当前字符不匹配
如果字符不同:
- 连续相同部分中断,当前长度重置为 0。
- 公式 :
dp[i][j] = 0
4. 代码逐行解释
java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextLine()) { // 处理多组输入
String text1 = in.nextLine(); // 输入字符串1
String text2 = in.nextLine(); // 输入字符串2
int m = text1.length(); // 字符串1的长度
int n = text2.length(); // 字符串2的长度
int[][] dp = new int[m + 1][n + 1]; // 创建动态规划表格
int result = 0; // 记录最长公共子串的长度
// 遍历字符串1的每个字符
for (int i = 1; i <= m; i++) {
char temp1 = text1.charAt(i - 1); // 当前字符
// 遍历字符串2的每个字符
for (int j = 1; j <= n; j++) {
char temp2 = text2.charAt(j - 1); // 当前字符
if (temp1 == temp2) { // 如果字符匹配
dp[i][j] = dp[i - 1][j - 1] + 1; // 长度 = 左上角值 + 1
result = Math.max(result, dp[i][j]); // 更新最大值
} else { // 如果字符不匹配
dp[i][j] = 0; // 重置为0
}
}
}
System.out.println(result); // 输出最长公共子串的长度
}
}
}
5. 实际例子
假设 text1 = "abcdefg"
,text2 = "zbcdf"
,它们的 最长公共子串 是 "bcd"
,长度为 3。填表过程如下:
a | b | c | d | e | f | g | ||
---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
z | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
b | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
c | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 0 |
d | 0 | 0 | 0 | 0 | 3 | 0 | 0 | 0 |
f | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
- 关键步骤 :
- 当
i=2
(字符b
)和j=2
(字符b
)时,匹配成功,长度更新为dp[1][1] + 1 = 0 + 1 = 1
。 - 当
i=3
(字符c
)和j=3
(字符c
)时,匹配成功,长度更新为dp[2][2] + 1 = 1 + 1 = 2
。 - 当
i=4
(字符d
)和j=4
(字符d
)时,匹配成功,长度更新为dp[3][3] + 1 = 2 + 1 = 3
。
- 当
6. 总结
- 核心思想:通过表格记录以每个字符结尾的最长公共子串长度,逐步推导全局最大值。
- 时间复杂度:O(mn),其中 m、n 是字符串长度。
- 适用场景:文本匹配、基因序列分析等需要找连续相同部分的场景。