问题描述
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'.
输入格式
- 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 in between.
输出格式
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.
样例输入
abcabcaa
acbacba
样例输出
ababa
abaca
abcba
acaba
acaca
acbaa
acbca
题目大意
求两个字符串的最长公共子串,并将所有方案输出。方案之间不能重复。
题解
首先显然要用动态规划的方法把最长公共子串的长度求出来。那么怎么输出方案呢?显然动态规划的方法行不通。因此我们可以尝试构造的方法来手动构造子串。设(f1[i][j])表示在第一个串中字符(i)在第(j)位前最晚出现的位置,同理也有(f2[i][j])。那么利用深搜从后往前构造,dfs的参数中分别为当前在第一个串中的位置(x),在第二个串中的位置(y),构造出来的子串(s)和还需要构造的长度(l)。在每一层中从(a)~(z)枚举,找出该字符在两个串中的最近的位置(记为p1和p2)。如果该字符在两个字符串中均存在且两个字符串在p1和p2处的最长公共子序列长度不小于(l),那么就继续递归。最后把所有构造出的子串按字典序排序即可。
代码
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#define N 82
using namespace std;
string a,b;
int i,j,la,lb,f[N][N],f1[N][N],f2[N][N];
vector<string> v;
void dfs(int x,int y,string s,int l)
{
if(x<0||y<0) return;
if(l<=0){
v.push_back(s);
return;
}
for(int i=0;i<26;i++){
int p1=f1[i][x],p2=f2[i][y];
if(f[p1][p2]>=l){
char c='a'+i;
dfs(p1-1,p2-1,c+s,l-1);
}
}
}
int main()
{
cin>>a>>b;
la=a.length();
lb=b.length();
for(i=la;i>=1;i--) a[i]=a[i-1];
for(i=lb;i>=1;i--) b[i]=b[i-1];
for(i=1;i<=la;i++){
for(j=1;j<=lb;j++){
f[i][j]=max(f[i-1][j],f[i][j-1]);
if(a[i]==b[j]) f[i][j]=max(f[i][j],f[i-1][j-1]+1);
}
}
for(i=0;i<26;i++){
for(j=1;j<=la;j++){
if(a[j]=='a'+i) f1[i][j]=j;
else f1[i][j]=f1[i][j-1];
}
for(j=1;j<=lb;j++){
if(b[j]=='a'+i) f2[i][j]=j;
else f2[i][j]=f2[i][j-1];
}
}
int len=f[la][lb];
dfs(la,lb,"",len);
sort(v.begin(),v.end());
for(i=0;i<v.size();i++) cout<<v[i]<<endl;
return 0;
}