Record some questions asked to write in the interview and other favorite questions: the longest palindrome substring + the longest substring without repeated characters + the longest common substring

Posted by bmyster on Tue, 21 Sep 2021 11:14:33 +0200

1. Question 5 of the longest palindrome substring force deduction

Substring: substring must be continuous, which is different from the concept of subsequence

Subsequence:

Where the violent solution can be optimized: palindromes are judged only when the length of the substring is > the current maximum length,

Is there anything that can be improved

class Solution {
public:
bool ishuiwen(string s){
    if(s.size()==1) return true;
    int i=0;
    int j=s.size()-1;
    while(i<=j){
        if(s[i]!=s[j]){
            return false;
        }
        ++i;
        --j;
    }
    return true;
}
    string longestPalindrome(string s) {
int n=s.size();
   int maxlength=0;
   int res_i=0;
   int i=0;
   for(;i<n;++i){
    for(int len=1;len<=n-i;++len){
        cout<<"i="<<i<<" len="<<len<<endl;
        
        
        if(len>maxlength){
            string temp=s.substr(i,len);
            if(ishuiwen(temp)){
                res_i=i;
                maxlength=len;
            }
        }
    }
   }
    cout<<"res_i="<<res_i<<" maxlength="<<maxlength<<endl;
    return s.substr(res_i,maxlength);
    }
};

Dynamic programming solution: note that maxlength is initialized to 1, otherwise the use case "ac" cannot pass. It finally passes. Then, you need to pay attention to the condition that J-I < 3   j-i+1<4.

The length between double pointer mode I and j is j-i+1,   If the length is less than 4, the possible length is 1,2,3. Under this else, s[i]==s[j], then it must be a palindrome substring

The reason why maxlength here should be initialized with 1?? Because in the following two nested for loops, maxlength may not be updated and still maintain the value of 0, which will produce incorrect results

You can also perform a separate processing on a string with length 2?? Maybe

class Solution {
public:
    string longestPalindrome(string s) {
     if(s.size()<2) return s;
     int n=s.size();
     vector<vector<int>> dp(n,vector<int>(n)); // In this case, all are initialized to 0// int dp[n][n];
     //i. J represents the left and right boundary state transition equation DP [i] [J] = 1 respectively. If (s [i] = = s [J] & & dp[i+1] DP [) for the substring with length of 2 or 3 with J-I < 3, the value of dp[i+1] [j-1] is not required
     for(int i=0;i<n;++i){//This piece is wrong!!
        dp[i][i]=1;
     }
     
    
     int maxlength=1, res_i=0;

     for(int j=1;j<n;++j){
        for(int i=0;i<j;++i){
            if(s[i]!=s[j]){
                dp[i][j]=0;
            }
            else{
                if(j-i<3){
                    dp[i][j]=1;
                }
                else{
                    if(dp[i+1][j-1]==1){
                        dp[i][j]=1;
                    }
                }
            }

           if(j-i+1>maxlength && dp[i][j]==1){
                res_i=i;
                maxlength=j-i+1;
           }
     }
     }
     

     return s.substr(res_i,maxlength);
    }
};

2. Longest common substring

Find the longest common substring for two strings

str1.find(str2) find str2 in str1. See the records on Youdao cloud notes

There is another way of violence,

You can remember this writing, using two pointers i and j     Two more pointers m and k

  while(m<length1 && k<length2 &&str1[m]==str2[k])   The key to this sentence is that we need to guarantee the legitimacy of M and K

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string str1,str2;
    str1="helloworld";
    str2="loop";
    //cin>>str1;
    //cin>>str2;
    int length1=str1.size(), length2=str2.size();
    int m,k,len,maxlength=0,res_i;
    for(int i=0;i<length1;++i){
        for(int j=0;j<length2;++j){
        m=i;
        k=j;
        len=0;
            while(m<length1 && k<length2 &&str1[m]==str2[k]){
                ++m;
                ++k;
                ++len;
            }
            if(len>maxlength){
                maxlength=len;
                res_i=i;
            }
        }
    }
    cout<<maxlength<<endl;
    cout<<str1.substr(res_i,maxlength);
    //cout << "Hello world!" << endl;
    return 0;
}

Solution of dynamic programming 1:

In fact, it is better not to name the array below this solution dp

In order to get results over and over again, some optimization should be done

class Solution {
public:
    /**
     * longest common substring
     * @param str1 string String the string
     * @param str2 string String the string
     * @return string character string
     */
    string LCS(string str1, string str2) {
        // write code here
        int m=str1.size(), n=str2.size();
        vector<vector<int>> dp(m,vector<int>(n,0));
        for(int i=0;i<m;++i){
            for(int j=0;j<n;++j){
                if(str1[i]==str2[j]){
                    dp[i][j]=1;
                }
            }
        }
        int maxlength=0,res_i=0;
        for(int i=0;i<m;++i){
            for(int j=0;j<n;++j){
                int temp=0;
                int u=i, v=j;
                while(u<m && v<n && dp[u][v]==1){
                    ++temp;
                    ++u;
                    ++v;
                }
                if(temp>maxlength){
                    maxlength=temp;
                    res_i=i;
                }
            }
        }
        
        return str1.substr(res_i,maxlength);
        
    }
};

Improve:

if(str1[i]!=str2[j]){

dp[i][j]=0;}

else{

if(i==0 || j==0) dp[i][j]=1;

else dp[i-1][j-1]+1;

3. Longest common subsequence

It also needs to use the solution of dynamic programming. 1. Determine the meaning of dp array and subscript. 2   2. Determine the state transition equation

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int m=text1.size();
        int n=text2.size();
        string a="@";
        text1=a+text1;
        cout<<text1<<endl;
        text2=a+text2;
        vector<vector<int>> dp(m+1,vector<int>(n+1,0));
        for(int i=1;i<m+1;++i){
            for(int j=1;j<n+1;++j){
                if(text1[i]==text2[j]){
                    dp[i][j]=dp[i-1][j-1]+1;
                }
                else{
                    dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        for(auto i:dp){
            for(auto j:i){
                cout<<j<<" ";
            }
            cout<<endl;
        }
        return dp[m][n];
    }
};

4. The sliding window algorithm to be used is:

Minimum window substring

Given two strings S and T, find the length of the shortest continuous substring containing all characters of T in S

Topics: leetcode Interview Dynamic Programming