BM66. [最长公共子串]

alt

https://www.nowcoder.com/exam/oj?tab=%E7%AE%97%E6%B3%95%E7%AF%87&topicId=295

BM66. 最长公共子串

https://www.nowcoder.com/practice/f33f5adc55f444baa0e0ca87ad8a6aac?tpId=295&sfm=discuss&channel=nowcoder

题目的主要信息:

  • 查找两个字符串str1,str2中的最长的公共子串
  • 保证str1和str2的最长公共子串存在且唯一
  • 进阶要求:时间复杂度:,空间复杂度:

方法一:暴力枚举
具体做法:

遍历str1每个字符作为起点,然后遍历以其为起点的每个长度的长度,即暴力枚举字符串str1的所有子串,用find函数查看每个子串是否在字符串str2中出现,如果出现比较长更新为较长的子串长度。

class Solution {
public:
    string LCS(string str1, string str2) {
        string res = "";
        for(int i = 0; i < str1.length(); i++){ //遍历sre1每个起始点的每个长度
            for(int j = i; j < str1.length(); j++){
                if(int(str2.find(str1.substr(i, j - i + 1))) < 0) //截取子串能够在str2中被找到
                    break;
                else if(res.length() < j - i + 1) //更新较长的子串
                    res = str1.substr(i, j - i + 1);
            }
        }
        return res;
    }
};

复杂度分析:

  • 时间复杂度:,其中是str1的长度,是str2的长度,枚举str1所有的子串需要,find函数查找str2中是否含有子串需要
  • 空间复杂度:,res属于返回必要空间
    方法二:枚举改进
  • 具体做法:*

其实找子串不用像方法一一样完全枚举,我们完全可以遍历两个字符串的所有字符串作为起始,然后同时开始检查字符是否相等,相等则不断后移,增加子串长度,如果不等说明以这两个为起点的子串截止了,不会再有了,后续比较长度维护最大值即可。

alt

class Solution {
public:
    string LCS(string str1, string str2) {
        int length = 0;
        string res = ""; 
        for(int i = 0; i < str1.length(); i++){ //遍历s1每个起始点
            for(int j = 0; j < str2.length(); j++){ //遍历s2每个起点
                int temp = 0;
                string temps = "";
                int x = i, y = j;
                while(x < str1.length() && y < str2.length() && str1[x] == str2[y]){ //比较每个起点为始的子串
                    temps += str1[x];
                    x++;
                    y++;
                    temp++;
                }
                if(length < temp){ //更新更大的长度子串
                    length = temp;
                    res = temps;
                }
            }
        }
        return res;
    }
};

复杂度分析:

  • 时间复杂度:,其中是str1的长度,是str2的长度,分别枚举两个字符串每个字符作为起点,后续检查子串长度最坏需要花费
  • 空间复杂度:,res属于返回必要空间,temps属于临时空间,最坏情况下长度为

方法三:动态规划
具体做法:

动态规划继承自方法二,我们可以用表示在str1中以第个字符结尾在str2中以第个字符结尾时的公共子串长度,遍历两个字符串填充dp数组,在这个过程中比较维护最大值即可。

转移方程为:如果遍历到的该位两个字符相等,则此时长度等于两个前一位长度+1,,如果遍历到该位时两个字符不相等,则置为0,因为这是子串,必须连续相等,断开要重新开始。

每次更新后,我们维护最大值,并更新该子串结束位置,最后根据最大值结束位置即可截取出子串。

class Solution {
public:
    string LCS(string str1, string str2) {
        vector<vector<int> > dp(str1.length() + 1, vector<int>(str2.length() + 1, 0)); //dp[i][j]表示到str1第i个个到str2第j个为止的公共子串长度
        int max = 0;
        int pos = 0;
        for(int i = 1; i <= str1.length(); i++){
            for(int j = 1; j <= str2.length(); j++){
                if(str1[i - 1] == str2[j - 1]){ //如果该两位相同
                    dp[i][j] = dp[i - 1][j - 1] + 1; //则增加长度
                }
                else{ //否则
                    dp[i][j] = 0; //该位置为0
                }
                if(dp[i][j] > max){ //更新最大长度
                    max = dp[i][j];
                    pos = i - 1;
                }
            }
        }
        return str1.substr(pos - max + 1, max);
    }
};

复杂度分析:

  • 时间复杂度:,其中是str1的长度,是str2的长度,遍历两个字符串所有字符
  • 空间复杂度:,dp数组大小为

alt

#面经##题解##面试题目#
全部评论

相关推荐

9.14一面介绍项目项目中的ETL项目中的拉链表项目中的UDF项目中的Kmeans和DBSCAN八股说一下HDFS说一下进程和线程说一下数据倾斜说一下kafka说一下数仓的建模(雪花,星形,星座)说一下数仓分层的作用OLAP和OLTP的区别说一下数据库三范式手撕两道SQL手写冒泡排序(一面全部答出来了)9.18二面,二面感觉很考验对大数据的理解介绍项目项目中感觉做的最好的地方是哪些介绍一下中国软件杯的比赛你觉得你的项目和比赛在哪些地方体现出了大数据的思路讲讲你对大数据的理解讲讲你对数仓分层的理解讲讲你对数据仓库和数据库的区别的理解数仓和数据库都是SQL&nbsp;Boy,&nbsp;你对两个SQL&nbsp;Boy的区别的理解有没有用过Doris和clickhouse(没有)说一下LSM&nbsp;Tree说一下Bit&nbsp;Map我看你项目里有lambda框架,讲一下lambda框架说一下Hive中的去重说一下模糊去重(这是真的不会。。。)说一下Kmeans和KNN的区别讲一下Java的集合框架手撕力扣原题,二叉树的层序遍历反问9.23&nbsp;HR面介绍一下你自己为什么选择大数据你是保研的,你的成绩排名是多少为什么不选择考公或者读博你认为现在公司需要什么样的人才你在秋招的时候是怎么介绍自己的你自己有什么优势(疯狂推销自己,我学习能力强)你说你学习能力强,怎么体现出来的(幸亏我脑子转的快,答上来了)两道场景题1.你入职后,你的师傅负责带你学习,但是刚过了一周,你的师傅被紧急抽调了。这种情况下你如何学习技术。2.入职后,有人得到了晋升,而你没有。但是你感觉你自己的付出不少于他们。你会怎么做。反问9.26&nbsp;oc&nbsp;#美团求职进展汇总#
点赞 评论 收藏
分享
3 2 评论
分享
牛客网
牛客企业服务