动态规划(二)最长公共子串和最长公共子序列

1.最长公共子序列

链接:https://www.nowcoder.com/questionTerminal/c996bbb77dd447d681ec6907ccfb488a
来源:牛客网

对于两个字符串,请设计一个高效算法,求他们的最长公共子序列的长度,这里的最长公共子序列定义为有两个序列U1,U2,U3…Un和V1,V2,V3…Vn,其中Ui<Ui+1,Vi<Vi+1。且A[Ui] == B[Vi]。
给定两个字符串A和B,同时给定两个串的长度n和m,请返回最长公共子序列的长度。保证两串长度均小于等于300。

测试样例:
"1A2C3D4B56",10,"B1D23CA45B6A",12
返回:6

这是经典的动态规划题目,定义子问题table[ i ][ j ]为字符串A的第一个字符到第 i 个字符串和字符串B的第一个字符串到第 j 个字符串的最长公共子序列,如A为“app”,B为“apple”,table[ 2 ][ 3 ]表示 “ap” 和 “app” 的最长公共字串。注意到代码中 table 的大小为 (n + 1) x (m + 1) ,这多出来的一行和一列是第 0 行和第 0 列,初始化为 0,表示空字符串和另一字符串的子串的最长公共子序列,例如table[ 0 ][ 3 ]表示 “” 和 “app” 的最长公共字串。
当我们要求table[ i ][ j ],我们要先判断A[ i ]和B[ j ]是否相同,如果相同他就是table[ i - 1 ][ j - 1 ] + 1,相当于在两个字符串都去掉一个字符时的最长公共字串再加 1;否则最长公共字串取table[ i ][ j - 1 ] 和table[ i - 1 ][ j ] 中大者。

链接:https://www.nowcoder.com/questionTerminal/c996bbb77dd447d681ec6907ccfb488a
来源:牛客网

class LCS {
public:
    int findLCS(string A, int n, string B, int m) {
        // write code here
        int table[n + 1][m + 1];

        for(int i = 0;i <= n;++i)
            table[i][0] = 0;
        for(int i = 0;i <= m;++i)
            table[0][i] = 0;

        for(int i = 1;i <= n;++i){
            for(int j = 1;j <= m;++j){
                if(A[i-1] == B[j-1])
                    table[i][j] = table[i-1][j-1] + 1;
                else {
                    table[i][j] = max(table[i][j - 1],table[i - 1][j]);
                }
            }
        }
        return table[n][m];
    }
};

字符串匹配

kmp算法
KMP算法 - CSDN博客
https://blog.csdn.net/coolwriter/article/details/79073116

最长公共连续子串

牛牛有两个字符串(可能包含空格),牛牛想找出其中最长的公共连续子串,希望你能帮助他,并输出其长度。
输入描述:

输入为两行字符串(可能包含空格),长度均小于等于50
输出描述:

输出为一个整数,表示最长公共连续子串的长度

输入例子:

abcde
abgde

输出例子:

2

解题思路:
这题其实是动态规划的变形经典题型,应用动态规划的思想,创建一个二维数组dp[n][n],其中dp[i][j],表示取到s1[i]和取到s2[j]时的最大连续子串长度。如果s1[i]等于s2[j],则dp[i-1][j-1]等于取到s1[i-1]和取到s2[j-1]时的最大连续子串长度加1,即
dp[i][j]=dp[i-1][j-1]+1。

#include   
#include   
#define N 50  
int main(){  
    char s1[N],s2[N];  
    int dp[N][N],i,j,max_len=0;  
    gets(s1);  
    gets(s2);  
    for(i=0;i<strlen(s1);i++){  
        for(j=0;j<strlen(s2);j++){  
            if(s1[i]==s2[j]){  
                if(i>0&&j>0){  
                    dp[i][j]=dp[i-1][j-1]+1;  
                }else{  
                    dp[i][j]=1;  
                }  
                if(max_lenprintf("%d\n",max_len);  
    return 0;  
}   

一定要把dp清零

class LongestSubstring {
public:
    int findLongest(string A, int n, string B, int m) {

        int max_len = 0;
        int matrix [10000][10000];
       for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                matrix[i][j] = 0;
            }
        }
       for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(A[i] == B[j]){
                    if(i > 0 && j > 0)
                        matrix[i][j] = matrix[i-1][j-1]+1;
                    else
                        matrix[i][j] = 1;
                }
                if(max_len < matrix[i][j])
                    max_len = matrix[i][j];
        }  
    }
        return max_len;
    }
};
class LongestSubstring {
public:
    int findLongest(string A, int n, string B, int m) {

        int max_len = 0;
        int matrix [1000][1000] = {0};

       for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(A[i] == B[j]){
                    if(i > 0 && j > 0)
                        matrix[i][j] = matrix[i-1][j-1]+1;
                    else
                        matrix[i][j] = 1;
                }
                if(max_len < matrix[i][j])
                    max_len = matrix[i][j];
        }  
    }
        return max_len;
    }
};

你可能感兴趣的:(动态规划)