Trip
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3850   Accepted: 1030

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

Source

题意:

求最长公共子序列,要求输出所有方案。

思路:

最长公共子序列好求,难点在输出方案。

用dp[i][j]表示处理到alice[i]和bob[j]时的最优解。如果alice[i]bob[j]不相等,dp[i][j]从dp[i-1][j], dp[j][i-1]中取较大的。相等,则dp[i-1][j-1]+1

先得到最优解,然后我们来输出所有方案。排序和去重都简单,用个set就行了。

首先我们预处理出alice串1~i的子串中,字符j+'a'最后一次出现的位置,存入pos1[i][j]。对bob串也做同样的处理。

然后我们进行递归。len1表示alice子串长度,len2表示bob子串长度,len表示公共串的子串长度。

枚举26个字母,找到他们在子串中最后出现的位置,如果我们发现dp[p1][p2] = len,那么说明这是一种可行的方案。并且这表示,这个字母会出现在这个方案的len位置。于是我们继续递归,去找(len1-1,len2-1,len-1)。直到len小于0了,说明现在当前跑出来的这个串跑完了,他是一个完整的方案,insert进set。如果在len到0之前,len1或者len2就已经小于0了,说明这个方案最后不可行了,也就不会insert,而会回溯。整个过程相当于是一个dfs。

WA了一次是因为输出了一下方案数的个数.....

 //#include <bits/stdc++.h>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<stdio.h>
#include<cstring>
#include<vector>
#include<map>
#include<set> #define inf 0x3f3f3f3f
using namespace std;
typedef long long LL; char alice[], bob[], tmp[];
int dp[][], pos1[][], pos2[][];
set<string> ans;
int lena, lenb; void solve(int len1, int len2, int len)
{
if(len <= ){
string str;
str = tmp + ;
//memset(tmp, 0, sizeof(tmp));
//cout<<str<<endl;
ans.insert(str);
return;
}
if(len1 > && len2 > ){
for(int i = ; i < ; i++){
int p1 = pos1[len1][i];
int p2 = pos2[len2][i];
if(dp[p1][p2] == len){
tmp[len] = i + 'a';
solve(p1 - , p2 - , len - );
}
}
} } int main()
{
while(scanf("%s%s", alice + , bob + ) != EOF){
lena = strlen(alice + );
lenb = strlen(bob + );
//ans.clear(); for(int i = ; i <= lena; i++){
dp[i][] = ;
}
for(int j = ; j <= lenb; j++){
dp[][j] = ;
} int tmpi = -, tmpj = -;
for(int i = ; i <= lena; i++){
for(int j = ; j <= lenb; j++){
dp[i][j] = max(dp[i][j], dp[i - ][j]);
dp[i][j] = max(dp[i][j], dp[i][j - ]);
if(alice[i] == bob[j]){
dp[i][j] = dp[i - ][j - ] + ;
}
}
} memset(pos1, -, sizeof(pos1));
memset(pos2, -, sizeof(pos2));
for(int i = ; i <= lena; i++){
for(int j = ; j < ; j++){
if(alice[i] == j +'a'){
pos1[i][j] = i;
}
else{
pos1[i][j] = pos1[i - ][j];
}
}
}
for(int i = ; i <= lenb; i++){
for(int j = ; j < ; j++){
if(bob[i] == j + 'a'){
pos2[i][j] = i;
}
else{
pos2[i][j] = pos2[i - ][j];
}
}
} //printf("%d\n", dp[lena][lenb]);
memset(tmp, , sizeof(tmp));
solve(lena, lenb, dp[lena][lenb]);
set<string>::iterator iter;
for(iter = ans.begin(); iter != ans.end(); iter++){
cout<<*iter<<endl;
} } return ;
}

poj1934 Trip【线性DP】【输出方案】的更多相关文章

  1. $Poj1934\ Trip$ 线性$DP+$搜索

    Luogu Description 爱丽丝和鲍伯想去度假,他们每个人都制定了一个参观城市的清单,该地区正好有26个城市,因此它们被编码为小写字母“a”到“z”.清单上可能重复出现某个城市.因为他们想一 ...

  2. 【题解】POJ1934 Trip (DP+记录方案)

    [题解]POJ1934 Trip (DP+记录方案) 题意: 传送门 刚开始我是这么设状态的(谁叫我DP没学好) \(dp(i,j)\)表示钦定选择\(i\)和\(j\)的LCS,然而你会发现这样钦定 ...

  3. 线性dp

    线性dp应该是dp中比较简单的一类,不过也有难的.(矩乘优化递推请出门右转) 线性dp一般是用前面的状态去推后面的,也有用后面往前面推的,这时候把循环顺序倒一倒就行了.如果有的题又要从前往后推又要从后 ...

  4. 线性DP之机器分配

    题目大意 自己瞅 (懒得打了) 思路 前面是很简单的线性dp,后面是模拟递归输出方案, 模拟递归可以设ny为机器数机器数,nx表示第nx个公司,tot为总盈利,那么则有\(a[nx][i]+dp[nx ...

  5. LightOJ1044 Palindrome Partitioning(区间DP+线性DP)

    问题问的是最少可以把一个字符串分成几段,使每段都是回文串. 一开始想直接区间DP,dp[i][j]表示子串[i,j]的答案,不过字符串长度1000,100W个状态,一个状态从多个状态转移来的,转移的时 ...

  6. Codeforces 176B (线性DP+字符串)

    题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28214 题目大意:源串有如下变形:每次将串切为两半,位置颠倒形成 ...

  7. hdu1712 线性dp

    //Accepted 400 KB 109 ms //dp线性 //dp[i][j]=max(dp[i-1][k]+a[i][j-k]) //在前i门课上花j天得到的最大分数,等于max(在前i-1门 ...

  8. 动态规划——线性dp

    我们在解决一些线性区间上的最优化问题的时候,往往也能够利用到动态规划的思想,这种问题可以叫做线性dp.在这篇文章中,我们将讨论有关线性dp的一些问题. 在有关线性dp问题中,有着几个比较经典而基础的模 ...

  9. POJ 2479-Maximum sum(线性dp)

    Maximum sum Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 33918   Accepted: 10504 Des ...

  10. poj 1050 To the Max(线性dp)

    题目链接:http://poj.org/problem?id=1050 思路分析: 该题目为经典的最大子矩阵和问题,属于线性dp问题:最大子矩阵为最大连续子段和的推广情况,最大连续子段和为一维问题,而 ...

随机推荐

  1. imx6 android5.1 编译

    imx6 android5.1 编译 记录一下编译imx6dl android的命令. Android build cd ~/myandroid source build/envsetup.sh lu ...

  2. dhcpcd 移植

    /************************************************************************ * dhcpcd移植 * dhcpcd是DHCP c ...

  3. centos7命令总结

    1,查看cpu信息 lscpu 2,网络配置 ip  route   查看路由 nmcli nmcli connection show    显示所有连接 nmcli connection show ...

  4. 【Java面试题】34 List 、Map、Set 区别?

    一.Set是最简单的一种集合.集合中的对象不按特定的方式排序,并且没有重复对象. Set接口主要实现了两个实现类: HashSet: HashSet类按照哈希算法来存取集合中的对象,存取速度比较快 T ...

  5. 【Java集合的详细研究3】Arrays类常用方法

    1.void sort(array)对数组array的元素进行升序排序 2.int binarySearch(array,val):查询元素值val在数组array中的下标 3.String toSt ...

  6. 【Java面试题】5 Integer的int 的种种比较?详细分析

    如果面试官问Integer与int的区别:估计大多数人只会说道两点,Ingeter是int的包装类,int的初值为0,Ingeter的初值为null.但是如果面试官再问一下Integer i = 1; ...

  7. 移动端meta 解释

    移动端meta 解释 <meta name="viewport" content="width=device-width, initial-scale=1.0, u ...

  8. nyoj-655-光棍的yy(大数)

    光棍的yy 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描写叙述 yy常常遇见一个奇怪的事情.每当他看时间的时候总会看见11:11,这个非常纠结啊. 如今给你m个1,你能够 ...

  9. Qt选择文件对话框-中文路径-转std::string

    #include <QFileDialog>#pragma execution_character_set("utf-8") QString path = QFileD ...

  10. 如何在CLI命令行下运行PHP脚本,同时向PHP脚本传递参数?

    <?php/* //命令行输入输出流fwrite(STDOUT,"Enter your name:"); $name = trim(fgets(STDOUT)); fwrit ...