题解 | #公共子串计算#

公共子串计算

http://www.nowcoder.com/practice/98dc82c094e043ccb7e0570e5342dd1b

HJ75公共子串计算

一.题目描述

给定两个只包含小写字母的字符串,计算两个字符串的最大公共子串的长度。

注:子串的定义指一个字符串删掉其部分前缀和后缀(也可以不删)后形成的字符串。

alt

二.算法一(暴力)

由于是字串是个连续的字符串,我们可以暴力循环的方法查找截取出长串的所有字串,判断其是否会在短串中出现,下面是完整代码:

#include <bits/stdc++.h>
using namespace std;
string a,b;
int main(){
    cin>>a>>b;
    //使得a串为长串
    if(a.size()<b.size()){
        swap(a,b);
    }
    for(int i=b.size();i>=0;i--){
        for(int j=0;j<b.size()-i+1;j++){
            //利用两次循环截取出短串所有的字串
            string now=b.substr(j,i);
            if(a.find(now)!=a.npos){
                //公共串的是从大到小进行截取的 所以找到直接输出 结束
                cout<<i<<endl;
                return 0;
            }
        }
    }
    return 0;
}

时间复杂度:O(n3)O(n^{3}),for两重循环加上每一次循环还要判断子串在不在长串中,所以复杂度达到了O(n3)O(n^{3})

空间复杂度:O(1)O(1),不需要什么额外的空间

三.算法二(动态规划)

前一种算法很显然时间上不是很优秀,我们可以换一种思维,使用动态规划的思路去解决,很显然这是很基本的最大公共字串问题。

alt

根据上述表格我们可以得到状态转移方程:

dp[i][j]表示以a[i],b[j]为最后一个元素的最长公共子串
当i=0或者j=0时候,dp[i][j]=0
当a[i]=b[j],dp[i][j]=dp[i-1][j-1]+1
当a[i]!=b[j],dp[i][j]=0

知道了状态转移方程我们就可以写出代码:

#include<bits/stdc++.h>
using namespace std;
const int N=155;
int dp[N][N];
//dp[i][j]表示以a[i],b[j]为最后一个元素的最长公共子串
string a,b;
int main(){
    cin>>a>>b;
    int n=a.size();
    int m=b.size();
    int mx=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<=m;j++){
            if(a[i-1]==b[j-1]){
                dp[i][j]=dp[i-1][j-1]+1;
            } else {
                dp[i][j]=0;
            }
            mx=max(mx,dp[i][j]);
        }
    }
    cout<<mx<<endl;
    return 0;
}

时间复杂度:O(n2)O(n^{2}),for两重循环循进行状态转移。

空间复杂度:O(n2)O(n^{2}),需要二维数组去记录状态转移方程。

全部评论
方法二有内存越界 for(int j=0;j<=m;j++){ if(a[i-1]==b[j-1]){
1 回复 分享
发布于 2022-04-08 12:53
动规的表格没看懂
点赞 回复 分享
发布于 2022-07-13 22:20
不是越界了吗。。
点赞 回复 分享
发布于 2022-07-30 22:19
动态规划的表格的一行一列是0不是1,写错了应该是,但是动规的思路和代码确实是正确的。
点赞 回复 分享
发布于 2022-12-21 10:04 广东

相关推荐

尊嘟假嘟点击就送:加v细说,问题很大
点赞 评论 收藏
分享
2024-11-15 19:28
已编辑
蚌埠坦克学院 硬件开发
点赞 评论 收藏
分享
🔌插電的小米大冰箱:很喜欢放牛,因为牛不会在我翻过第四座山后跟我说第一座山的草好吃
点赞 评论 收藏
分享
评论
15
2
分享
牛客网
牛客企业服务