1 solutions
-
1
思路
最长公共子串
简化题意
给定两个字符串 和 ,问两个字符串的最长公共子串长度。
的长度为 , 的长度为
暴力做法
枚举 的每个子串是否在 中找到,即朴素的字符串匹配算法,每次匹配是 的。 枚举每个 的子串,则是以 的每个索引开始,依次和 进行比较,如果存在 的某个字符和对应的 的字符不匹配了,则说明后续也不会匹配了,这样的复杂度为 。
优化暴力做法
表示以 和 结尾的子字符串的相同的最大长度。 如果 ,必然有 $s[i-k+1]=t[j-k+1],s[i-k+2]=t[j-k+2],\cdots s[i]=t[j]$。故 是从 转移而来的。
状态转移方程为:
最后取所有 的 即可。
类似题目推荐
LeetCode
Codefun2000
代码
CPP
#include <bits/stdc++.h> using namespace std; const int N = 1010; int f[N][N]; char s[N], t[N]; int ns, nt; int main() { scanf("%s%s", s + 1, t + 1); ns = strlen(s + 1), nt = strlen(t + 1); // 最长公共子串 int ans = 0; // 枚举 s 中子串的最后一个字符 for (int i = 1; i <= ns; ++i) { // 枚举 t 中子串的最后一个字符 for (int j = 1; j <= nt; ++j) { // 如果两个尾字符相等,才会有长度至少为 1 的公共子串 if (s[i] == t[j]) { // 状态转移 f[i][j] = f[i - 1][j - 1] + 1; // 更新答案 ans = max(ans, f[i][j]); } } } printf("%d\n", ans); }
python
N = 1010 f = [[0]*N for _ in range(N)] s = input().strip() t = input().strip() ns, nt = len(s), len(t) # 最长公共子串 ans = 0 # 枚举 s 中子串的最后一个字符 for i in range(1, ns+1): # 枚举 t 中子串的最后一个字符 for j in range(1, nt+1): # 如果两个尾字符相等,才会有长度至少为 1 的公共子串 if s[i-1] == t[j-1]: # 状态转移 f[i][j] = f[i-1][j-1] + 1 # 更新答案 ans = max(ans, f[i][j]) print(ans)
Java
import java.util.*; public class Main { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int N = 1010; int[][] f = new int[N][N]; char[] s = scan.next().toCharArray(); char[] t = scan.next().toCharArray(); int ns = s.length, nt = t.length; // 最长公共子串 int ans = 0; // 枚举 s 中子串的最后一个字符 for (int i = 1; i <= ns; ++i) { // 枚举 t 中子串的最后一个字符 for (int j = 1; j <= nt; ++j) { // 如果两个尾字符相等,才会有长度至少为 1 的公共子串 if (s[i-1] == t[j-1]) { // 状态转移 f[i][j] = f[i - 1][j - 1] + 1; // 更新答案 ans = Math.max(ans, f[i][j]); } } } System.out.println(ans); } }
Go
package main import ( "fmt" ) func main() { const N int = 1010 var f [N][N]int var s, t string fmt.Scan(&s, &t) ns, nt := len(s), len(t) // 最长公共子串 ans := 0 // 枚举 s 中子串的最后一个字符 for i := 1; i <= ns; i++ { // 枚举 t 中子串的最后一个字符 for j := 1; j <= nt; j++ { // 如果两个尾字符相等,才会有长度至少为 1 的公共子串 if s[i-1] == t[j-1] { // 状态转移 f[i][j] = f[i-1][j-1] + 1 // 更新答案 if f[i][j] > ans { ans = f[i][j] } } } } fmt.Println(ans) }
Js
process.stdin.resume(); process.stdin.setEncoding('utf-8'); let input = ''; process.stdin.on('data', (data) => { input += data; return; }); process.stdin.on('end', () => { const lines = input.trim().split('\n'); const N = 1010; const f = new Array(N).fill().map(() => new Array(N).fill(0)); const s = lines[0]; const t = lines[1]; const ns = s.length, nt = t.length; // 最长公共子串 let ans = 0; // 枚举 s 中子串的最后一个字符 for (let i = 1; i <= ns; ++i) { // 枚举 t 中子串的最后一个字符 for (let j = 1; j <= nt; ++j) { // 如果两个尾字符相等,才会有长度至少为 1 的公共子串 if (s[i-1] == t[j-1]) { // 状态转移 f[i][j] = f[i - 1][j - 1] + 1; // 更新答案 ans = Math.max(ans, f[i][j]); } } } console.log(ans); });
- 1
Information
- ID
- 10
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 3
- Tags
- # Submissions
- 176
- Accepted
- 44
- Uploaded By