poj 1934 Trip 题解(加强版最长公共子序列)

点击打开链接
Trip
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 2967   Accepted: 760

Description

Alice and Bob want to go on holiday. Each of them has planned a route, which is a list of cities to be visited in a given order. A route may contain a city more than once. 
As they want to travel together, they have to agree on a common route. None wants to change the order of the cities on his or her route or add other cities. Therefore they have no choice but to remove some cities from the route. Of course the common route should be as long as possible. 
There are exactly 26 cities in the region. Therefore they are encoded on the lists as lower case letters from 'a' to 'z'.

Input

The input consists of two lines; the first line is Alice's list, the second line is Bob's list. 
Each list consists of 1 to 80 lower case letters with no spaces inbetween.

Output

The output should contain all routes that meet the conditions described above, but no route should be listed more than once. Each route should be printed on a separate line. There is at least one such non-empty route, but never more than 1000 different ones. Output them in ascending order.

Sample Input

abcabcaa
acbacba

Sample Output

ababa
abaca
abcba
acaba
acaca
acbaa
acbca
题意:输出两个串所有的最长公共子序列。
一开始我在dp的过程中记录每个状态的前驱,然后暴搜,结果TLE了。。虽然题目说答案中不同的串不超过1000个,但由于重复的串太多,暴搜不能过。看了看大牛们的解题报告,我只能再一次膜拜了!!!!方法如下:
首先求出最长公共子序列,然后处理处两个数组,f1['a'~'z'][j]表示该字母在第一个串的前j个字母中出现的最大下标,
f2['a'~'z'][j]表示该字母在第二个串的前j个字母中出现的最大下标。现在我们已经知道了最长公共子序列的长度,我们从最后一位开始枚举每一位放什么字母,用dfs来实现,并用前面处理出来的数组进行可行性剪枝。由于最后答案的串不超过1000个,所以暴搜的复杂度可以接受。具体细节见代码:
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>
#include<math.h>
#define nn 110
#define inff 0x3fffffff
#define mod 1000000007
#define eps 1e-9
using namespace std;
typedef long long LL;
string a,b;
int dp[110][110];
int f1[30][110],f2[30][110];
vector<string>ans;
void dfs(int x,int y,string s,int l)
{
    if(x<0||y<0)
        return ;
    if(l<=0)//搜到了最底层,得到一个解
    {
        ans.push_back(s);
        return ;
    }
    int i,ix1,ix2;
    char fc;
    for(i=0;i<26;i++)
    {
        ix1=f1[i][x];
        ix2=f2[i][y];
        if(dp[ix1][ix2]==l)//第l位放(i+'a')字母可行
        {
            fc='a'+i;
            dfs(ix1-1,ix2-1,fc+s,l-1);
        }
    }
}
int main()
{
    int i,j;
    while(cin>>a)
    {
        cin>>b;
        int la=a.size(),lb=b.size();
        memset(dp,0,sizeof(dp));
        ans.clear();
        for(i=1;i<=la;i++)
        {
            for(j=1;j<=lb;j++)
            {
                if(a[i-1]==b[j-1])
                {
                    dp[i][j]=dp[i-1][j-1]+1;
                }
                else
                {
                    dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        for(i=0;i<26;i++)
        {
            f1[i][0]=0;
            for(j=1;j<=la;j++)
            {
                if(a[j-1]=='a'+i)
                    f1[i][j]=j;
                else
                    f1[i][j]=f1[i][j-1];
            }
        }
        for(i=0;i<26;i++)
        {
            f2[i][0]=0;
            for(j=1;j<=lb;j++)
            {
                if(b[j-1]=='a'+i)
                    f2[i][j]=j;
                else
                    f2[i][j]=f2[i][j-1];
            }
        }
        dfs(la,lb,"",dp[la][lb]);
        sort(ans.begin(),ans.end());
        for(i=0;i<(int)ans.size();i++)
        {
            cout<<ans[i]<<endl;
        }
    }
}


你可能感兴趣的:(dp,搜索,动态规划,ACM,DFS)