求最长公共子序列的子序列 dfs+dp

朋友分享的一道面试题

请输入图片描述

要求删除掉任意长度的字符串s1之后,获得的最长的回文串都有哪些?
因为回文串的性质,反转后不变,那么可以将字符串s1反转成s2。
如果存在一个最长的回文串,那么肯定是s1和s2的最长公共子序列。
通常我们会求出最长公共子序列的长度alen,这次要把所有的子序列输出来。

可以通过观察dp矩阵,发现这样一个规律(图忘记从哪里盗来的了)

可以通过标有圆圈的点,找到所有的子串,标有圆圈的点,可以通过s1[i]==s2[j]找到,然后可以放在一个二维数组里。

然后进一步通过dfs,去找下一个标有圆圈的点,如果找到的长度为alen了,说明这就是一个答案,因为是通过遍历所有可能解,所以可能存在重复值,可以用set去重。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <set>
using namespace std;
const int maxn = 1005;
int len;        //当前长度 
int alen;        //总长度 
int ans;        
int top;
int top2;
int dp[maxn][maxn];
int arr[2][maxn];
char stc[maxn];
string s1,s2;
set<string> col;

string reverseStr(string s1){    //字符串反转 
    string s2 = s1;
    reverse(s2.begin(),s2.end());
    return s2;
}
void init(){                    //dp矩阵初始化 
    for(int i=0;i<maxn;++i){
        for(int j=0;j<maxn;++j){
            dp[i][j]=0;
        }
    }
}
void printMap(int len1,int len2){        //打印dp 
    for(int i=1;i<=len1;++i){
        for(int j=1;j<=len2;++j){
            cout<<dp[i][j]<<" ";
        }
        cout<<endl;
    }
}

void dfs(int x,int y,int pos){            //dfs搜索符合总长度的子串 
    if(top2==alen){
        stc[top2]='\0';
        //cout<<stc<<endl;
        col.insert(stc);
    }
    for(int i=pos+1;i<top;++i){
        if(arr[0][i]>arr[0][pos] && arr[1][i]>arr[1][pos]){
            stc[top2++] = s1[arr[0][i]-1];        
            dfs(arr[0][i],arr[1][i],i);
            top2--;    
        }
    }
}

int main(){
    //string s1,s2;
    while(cin>>s1){
        //memset(dp,0,sizeof(dp));
        init();
        s2=reverseStr(s1);
        //cout<<s2<<endl;
        int len1 = s1.length();
        int len2 = s2.length();
        //map(len1,len2);
        //dp求出最长子序列长度 
        int i , j ;
        for( i = 1; i <= len1;++i){
            for( j = 1 ; j <= len2;++j){
                if(s1[i-1] == s2[j-1]){
                    dp[i][j] =  dp[i-1][j-1] + 1;
                } else {
                    dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
                } 
            }
        }
        alen=dp[len1][len2]; 
        //printMap(len1,len2);
        //cout<<dp[len1][len2]<<endl;
        top=0;

        for(int i=0;i<len1;++i){
            for(int j=0;j<len2;++j){
                if(s1[i]==s2[j]) { 
                    arr[0][top] = i+1;
                    arr[1][top++] = j+1;
                }
            }
        }
        
        col.clear();    
        for(int i=0;i<top;++i){
            stc[top2++]=s1[arr[0][i]-1];
            dfs(arr[0][i],arr[1][i],i);
            top2--;
        }
        set<string>::iterator iter;
        //cout<<col.size()<<" !!!"<<endl;
        for(iter=col.begin();iter!=col.end();++iter){
            cout<<*iter<<endl;
        }
    }
    return 0;
} 
Last modification:November 11th, 2019 at 05:59 pm
如果觉得我的文章对你有用,请随意赞赏