当前位置:网站首页>ACM. HJ75 公共子串计算 ●●
ACM. HJ75 公共子串计算 ●●
2022-06-24 23:40:00 【chenyfan_】
HJ75 公共子串计算 ●●
描述
给定两个只包含小写字母的字符串,计算两个字符串的最大公共子串的长度。
注:子串的定义指一个字符串删掉其部分前缀和后缀(也可以不删)后形成的字符串。
数据范围:字符串长度: 1 ≤ s ≤ 150 1\le s\le 150 1≤s≤150
进阶:时间复杂度: O ( n 3 ) O(n^3) O(n3),空间复杂度: O ( n ) O(n) O(n)
输入描述:
输入两个只包含小写字母的字符串
输出描述:
输出一个整数,代表最大公共子串的长度
示例
输入:
asdfas
werasdfaswer
输出:
6
题解
本题与 LC 718. 最长重复子数组类似。
解法可见 C++ 数据结构与算法(十三)(动态规划 – 打家劫舍、股票问题、子序列问题)。
1. 动态规划
dp[i][j]表示以s1[i-1]、s2[j-1]为结尾(一定包括这两个字符)的字符串的公共子串长度(不一定是最大);- 初始化为0;
- 如果
s1[i-1] == s2[j-1],那么dp[i][j] = dp[i-1][j-1] + 1;,并比较更新最大长度;
否则,字符串结尾不相等,即公共长度为0. - 从前往后遍历。

- 时间复杂度: O ( n × m ) O(n × m) O(n×m),n 为A长度,m为B长度
- 空间复杂度: O ( n × m ) O(n × m) O(n×m)
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main(){
string s1, s2;
while(cin >> s1 >> s2){
int n = s1.length(), m = s2.length(), ans = 0;
vector<vector<int>> dp(n+1, vector<int>(m+1, 0));
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= m; ++j){
if(s1[i-1] == s2[j-1]){
// 所选字符串结尾相等
dp[i][j] = dp[i-1][j-1] + 1; // 上一串长度 + 1
ans = max(ans, dp[i][j]);
} // s1[i-1] != s2[j-1] 即结尾不相同,长度为0
}
}
cout << ans << endl;
}
return 0;
}
- 一维滚动数组优化空间复杂度 O(n)
dp[i][j] 都是由dp[i - 1][j - 1]推出。那么压缩为一维数组,也就是dp[j]都是由dp[j - 1]推出。
也就是相当于可以把上一层dp[i - 1][j]拷贝到下一层dp[i][j]来继续用。
此时遍历B数组的时候,就要从后向前遍历,这样避免重复覆盖,且长度为 0 时要注意赋值。
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main(){
string s1, s2;
while(cin >> s1 >> s2){
int n = s1.length(), m = s2.length(), ans = 0;
vector<int> dp(m+1, 0);
for(int i = 1; i <= n; ++i){
for(int j = m; j >= 1; --j){
if(s1[i-1] == s2[j-1]){
dp[j] = dp[j-1] + 1; // 相等
ans = max(ans, dp[j]);
}else{
dp[j] = 0; // 不相等
}
}
}
cout << ans << endl;
}
return 0;
}
2. 滑动窗口
通过滑动字符串来遍历所有字符串重叠的情况,然后在重叠部分找最大公共子串的长度。
如图可知,枚举 字符串 所有的重叠(对齐)方式主要分为三步(s1长度更小):
(1)s1 尾部开始与 s2 重叠,直到 s1 完全被覆盖;
(2)s1 头部与 s2 头部开始错位,直到 s1 尾部 与 s2 尾部重叠;
(3)s1 尾部超过 s2 尾部,直到不再重叠。
每次滑动操作需要更新两个字符串的重叠起始下标和结束下标。
- 时间复杂度: O ( ( N + M ) × min ( N , M ) ) O((N + M) \times \min(N, M)) O((N+M)×min(N,M))
- 空间复杂度: O ( 1 ) O(1) O(1)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int getLen(string s1, string s2, int a1, int b1, int a2, int b2){
// 找到s1[a1, b1]和s2[a2,b2]的最大公共子串长度
int n = b1 - a1 + 1;
int pre = 0, ans = 0;
for(int i = 0; i < n; ++i){
if(s1[a1 + i] == s2[a2 + i]){
ans = max(ans, pre + 1);
++pre;
}else{
pre = 0;
}
}
return ans;
}
int main(){
string s1, s2;
// 滑动窗口
while(cin >> s1 >> s2){
if(s1.length() > s2.length()) swap(s1, s2);
int n = s1.length(), m = s2.length(), ans = 0; // s1 更短
for(int i = 1; i <= n; ++i){
// s1 尾部开始与 s2 重叠,直到 s1 完全被覆盖
int subLen = getLen(s1, s2, n-i, n-1, 0, i-1);
ans = max(ans, subLen);
}
for(int i = 1; i <= m-n; ++i){
// s1 头部与 s2 头部开始错位,直到 s1 尾部 与 s2 尾部重叠
int subLen = getLen(s1, s2, 0, n-1, i, n+i-1);
ans = max(ans, subLen);
}
for(int i = 1; i < n; ++i){
// s1 尾部超过 s2 尾部,直到不再重叠
int subLen = getLen(s1, s2, 0, n-1-i, m-2-n+i, m-1);
ans = max(ans, subLen);
}
cout << ans << endl;
}
return 0;
}
边栏推荐
- Call system function security scheme
- E - Average and Median(二分)
- The role of software security testing, how to find a software security testing company to issue a report?
- centos7.3修改mysql默认密码_详解Centos7 修改mysql指定用户的密码
- 爱
- ERROR日志格式与注意点
- Are programmers from Huawei, Alibaba and other large manufacturers really easy to find?
- Software testing salary in first tier cities - are you dragging your feet
- Of the seven levels of software testers, it is said that only 1% can achieve level 7
- Using qdomdocument to manipulate XML files in QT
猜你喜欢

记一次beego通过go get命令后找不到bee.exe的坑

1-6搭建Win7虚拟机环境

Leecode learning notes - the shortest path for a robot to reach its destination

进入阿里做测试员遥不可及?这里或许有你想要的答案

【STL源码剖析】STL六大组件功能与运用(目录)

使用ShaderGraph制作边缘融合粒子Shader的启示

jwt

Please run IDA with elevated permissons for local debugging.

Are programmers from Huawei, Alibaba and other large manufacturers really easy to find?

LeetCode 210:课程表 II (拓扑排序)
随机推荐
Charles packet capturing tool
Error log format and precautions
centos7.3修改mysql默认密码_详解Centos7 修改mysql指定用户的密码
Network planning | [four network layers] knowledge points and examples
Software testing salary in first tier cities - are you dragging your feet
保险也能拼购?个人可以凑够人数组团购买医疗保险的4大风险
会自动化—10K,能做自动化—20K,你搞懂自动化测试没有?
Jetson nano from introduction to practice (cases: opencv configuration, face detection, QR code detection)
Is the compass reliable? Is it safe to open a securities account?
Once beego failed to find bee after passing the go get command Exe's pit
Intranet learning notes (5)
计网 | 【四 网络层】知识点及例题
LINQ query (3)
保险APP适老化服务评测分析2022第06期
Is it out of reach to enter Ali as a tester? Here may be the answer you want
PE文件基础结构梳理
计算机三级(数据库)备考题目知识点总结
折叠屏将成国产手机分食苹果市场的重要武器
MySQL command backup
vim的Dirvish中文文档