【POJ1934】 Trip

                                                                                             Trip

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3661   Accepted: 978

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

解析:

       最长公共子序列+输出方案。

      省略掉最长公共子序列的计算方法,我们直接考虑怎样输出方案,在网上看到一篇讲得比较详细的博客,现贴在这以供参考。原文

首先分别计算两个输入串的loc[i][j].str1 的loc[i][j]表示在str1中位于位置i以及它之前的且距离i最 近的字母j的位置,则可以得到:

     loc[i][j] = i当 str[i] == j; 

     loc[i - 1][j]当 str[i] != j 

首先需要对输入串计算一变LCA,即LCA[i][j]表示两个串str1[1...i]与str2[1...j]的LCA的长度:

     LCA[i][j] = LCA[i - 1][j - 1], 当 str1[i] == str2[j]; 

     max(LCA[i - 1][j], LCA[i][j - 1]), 当 str1[i] != str2[j] 

然后从两个串的末尾递推,假设当前处理到两个串的位置分别为n,m 

那么 

如果str1[n] == str2[m],则将当前字符str1[n]加入结果字符串res,同时n,m的位置分别向前推进1变为n - 1, m - 1 

如果str1[n] != str2[m],则遍历所有的26个字母,找到LCA[loc1[n][k], loc2[m][k]]最大的那些k的位置, 

并向前推进,将n, m分别更新为loc1[n][k], loc2[m][k] 

 代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <queue>
using namespace std;

const int Max=100;
int t,n,m,tot;
char ans[Max],ch1[Max],ch2[Max];
int pos1[Max][26],pos2[Max][26],f[Max][Max];
struct item { char str[Max]; } com;
priority_queue<item, vector<item>, greater<item> > que;
bool operator> ( const item &a, const item &b )  //按照字典序排序
{
	if (  strcmp  ( a.str, b.str ) > 0 )
		return true;
	return false;
}

inline int mx(int x,int y) {return x > y ? x : y;}
inline void dfs(int p1,int p2,int len)
{
	if(!len)
	{
	  que.push(com);
	  return;
	}
	if(p1 < 1 || p2 < 1) return;
	for(int i=0;i<=25;i++)
	{
	  int po1 = pos1[p1][i],po2 = pos2[p2][i];
	  if(f[po1][po2] == len)
	  {
	    //ans[len] = ch1[po1];
	    com.str[len-1] = 'a' + i;
		dfs(po1-1,po2-1,len-1);
	  }
	}
}

int main()
{
	  scanf("%s\n%s",ch1+1,ch2+1);
	  n=strlen(ch1+1),m=strlen(ch2+1);
	  for(int i=1;i<=n;i++)
	    for(int j=1;j<=m;j++)
	    {
	      if(ch1[i] == ch2[j]) f[i][j] = f[i-1][j-1] + 1;
	      else f[i][j] = mx(f[i][j-1],f[i-1][j]);
	    }

	  for(int i=1;i<=n;i++)
	    for(int j=0;j<=25;j++)
	      if(ch1[i] == 'a' + j) pos1[i][j] = i;
	      else pos1[i][j] = pos1[i-1][j];
	  for(int i=1;i<=m;i++)
	    for(int j=0;j<=25;j++)
	      if(ch2[i] == 'a' + j) pos2[i][j] = i;
	      else pos2[i][j] = pos2[i-1][j];

	   dfs(n,m,f[n][m]);
	   while ( ! que.empty () )
	  {
   		printf("%s\n", que.top().str);
		que.pop();
	  }	

	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38083668/article/details/81269249