POJ1934:Trip(LCS)

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

CEOI 2003

题意:两个字符串,按字典序输出其所有的LCS

思路:先求出LCS的长度,vis[i][j]记录到i位置时,以j结尾的最后一个位置,然后再从尾往前比较,得出所有LCS,使用set存储,可以自动排序

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace std;
#define ls 2*i
#define rs 2*i+1
#define up(i,x,y) for(i=x;i<=y;i++)
#define down(i,x,y) for(i=x;i>=y;i--)
#define mem(a,x) memset(a,x,sizeof(a))
#define w(a) while(a)
#define LL long long
const double pi = acos(-1.0);
#define N 105
#define mod 19999997
const int INF = 0x3f3f3f3f;
#define exp 1e-8

char str1[N],str2[N],tmp[N];
int dp[N][N],len1,len2,len,vis1[105][30],vis2[105][30];
set<string> ans;
void LCS()
{
    int i,j;
    mem(dp,0);
    up(i,1,len1)
    {
        up(j,1,len2)
        {
            if(str1[i]==str2[j])
                dp[i][j]=dp[i-1][j-1]+1;
            else
                dp[i][j] = max(dp[i][j],max(dp[i-1][j],dp[i][j-1]));
        }
    }
    len = dp[len1][len2];
}

void solve(int l1,int l2,int len)
{
    int i,p1,p2;
    if(len<=0)
    {
        ans.insert(&tmp[1]);
        return ;
    }
    if(l1>0 && l2>0)
    {
        up(i,0,25)
        {
            p1 = vis1[l1][i];
            p2 = vis2[l2][i];
            if(dp[p1][p2]==len)
            {
                tmp[len]=i+'a';
                solve(p1-1,p2-1,len-1);
            }
        }
    }
}

int main()
{
    int i,j,k;
    w(~scanf("%s%s",str1+1,str2+1))
    {
        len1 = strlen(str1+1);
        len2 = strlen(str2+1);
        LCS();
        mem(vis1,0);
        mem(vis2,0);
        up(i,1,len1)
        {
            up(j,0,25)
            {
                if(str1[i]==j+'a')
                    vis1[i][j]=i;
                else
                    vis1[i][j]=vis1[i-1][j];
            }
        }
        up(i,1,len2)
        {
            up(j,0,25)
            {
                if(str2[i]==j+'a')
                    vis2[i][j]=i;
                else
                    vis2[i][j]=vis2[i-1][j];
            }
        }
        mem(tmp,'\0');
        solve(len1,len2,len);
        set<string>::iterator it;
        for(it = ans.begin(); it!=ans.end(); it++)
            printf("%s\n",(*it).c_str());
    }

    return 0;
}
时间: 2024-10-14 04:23:57

POJ1934:Trip(LCS)的相关文章

SPOJ33&amp;POJ1934 Trip DP、枚举

题目传送门:https://www.luogu.org/problemnew/show/SP33 题目大意:给出两个字符串,求其LCS(最长公共子序列)的长度与具体方案(相同的串算作同一方案).数据组数$\leq 10$,字符串长度$\leq 80$,方案数$\leq 1000$ 本来以为这是一道LCS水题,结果超级low的各种输出方案的方法TLE到怀疑人生 于是一个高大上的输出方法出现(借鉴于https://blog.csdn.net/gg_gogoing/article/details/41

poj 1934 Trip (LCS)

/* 按升序输出两个串所有的最长公共子序列 首先求出最长公共子序列,然后处理处两个数组,f1['a'~'z'][j]表示该字母在第一个串的前j个字母中出现的最大下标, f2['a'~'z'][j]表示该字母在第二个串的前j个字母中出现的最大下标.现在我们已经知道了最长公共子序列的长度, 我们从最后一位开始枚举每一位放什么字母,用dfs来实现,并用前面处理出来的数组进行可行性剪枝. 由于最后答案的串不超过1000个,所以暴搜的复杂度可以接受. */ # include <stdio.h> # i

POJ 1934 Trip(LCS+枚举+输出所有路径)

这道题一看就是LCS,直接写个裸的,硬搜.TLE void print(int r,int c,int n) { if(dp[r][c]==0) { string ss=tp; ans[ss]=1; //sprintf(ansstr[cnt++],"%s\n",tp); return; } if(ph[r][c]==1) tp[n]=sa[r-1],print(r-1,c-1,n-1); else if(ph[r][c]==3) print(r,c-1,n),print(r-1,c,n

HDU 1513 Palindrome:LCS(最长公共子序列)or 记忆化搜索

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1513 题意: 给你一个字符串s,你可以在s中的任意位置添加任意字符,问你将s变成一个回文串最少需要添加字符的个数. 题解1(LCS): 很神奇的做法. 先求s和s的反串的LCS,也就是原串中已经满足回文性质的字符个数. 然后要变成回文串的话,只需要为剩下的每个落单的字符,相应地插入一个和它相同的字符即可. 所以答案是:s.size()-LCS(s,rev(s)) 另外,求LCS时只会用到lcs[i-

poj 1080 (LCS变形)

Human Gene Functions 题意: LCS: 设dp[i][j]为前i,j的最长公共序列长度: dp[i][j] = dp[i-1][j-1]+1;(a[i] == b[j]) dp[i][j] = max(dp[i][j-1],dp[i-1][j]); 边界:dp[0][j] = 0(j<b.size) ,dp[i][0] = 0(i< a.size); LCS变形: 设dp[i][j]为前i,j的最大价值: value(x, y)为比较价值: dp[i][j] = max(d

POJ 1080 Human Gene Functions(LCS)

Description It is well known that a human gene can be considered as a sequence, consisting of four nucleotides, which are simply denoted by four letters, A, C, G, and T. Biologists have been interested in identifying human genes and determining their

POJ 1041 John&#39;s trip 无向图的【欧拉回路】路径输出

欧拉回路第一题TVT 本题的一个小技巧在于: [建立一个存放点与边关系的邻接矩阵] 1.先判断是否存在欧拉路径 无向图: 欧拉回路:连通 + 所有定点的度为偶数 欧拉路径:连通 + 除源点和终点外都为偶数 有向图: 欧拉回路:连通 + 所有点的入度 == 出度 欧拉路径:连通 + 源点 出度-入度=1 && 终点 入度 - 出度 = 1 && 其余点 入度 == 出度: 2.求欧拉路径 : step 1:选取起点(如果是点的度数全为偶数任意点为S如果有两个点的度数位奇数取一

最长公共子序列(LCS)问题

最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)的区别为:子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列:也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续. 1.序列str1和序列str2 ·长度分别为m和n: ·创建1个二维数组L[m.n]: ·初始化L数组内容为0 ·m和n分别从0开始,m++,n++循环: - 如果str1[m] ==

hdu 1503 LCS输出路径【dp】

hdu 1503 不知道最后怎么输出,因为公共部分只输出一次.有人说回溯输出,感觉好巧妙!其实就是下图,输出的就是那条灰色的路径,但是初始时边界一定要初始化一下,因为最第一列只能向上走,第一行只能向左走.我用1表示向上走,2向左上方走,3向左走. 刚开始输入字符串时有两种方法,直接输入:或从地址后一位输入,即此时数组起始编号为1.直接输入时,dp[i][j]表示的是以s1[i-1],s2[j-1]为结尾LCS,另一种则就是表示以s1[i],s2[j]为结尾的LCS.两者在路径输出时有些差别,以前