LCS 模板,但要输出具体方案,这就很毒瘤了。
神奇的预处理:fa[i][j]
表示在 (a) 串的前 (i) 个字符中,字母表第 (j) 个字母最晚出现的位置,fb[i][j]
同理。
这样我们便可以递归找路径,对于两指针的位置的字母相同就向下递归,否则用预处理数组枚举相同位置再递归。
还要按字典序输出,开个set
就行了。
#include <bits/stdc++.h>
using namespace std;
const int N=85;
char a[N],b[N],s[N];
int ans,f[N][N],fa[N][26],fb[N][26];
set<string> ss;
void getPath(int n,int m,int len)
{
if(!len)
{
string t;
for(int i=1;i<=ans;++i) t+=s[i];
ss.insert(t); return;
}
if(!n||!m) return;
if(a[n]==b[m])
{
s[len]=a[n];
getPath(n-1,m-1,len-1);
}
else
{
for(int i=0;i<26;++i)
if(f[fa[n][i]][fb[m][i]]==len)
getPath(fa[n][i],fb[m][i],len);
}
}
int main()
{
scanf("%s %s",a+1,b+1);
int n=strlen(a+1),m=strlen(b+1);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(a[i]==b[j]) f[i][j]=f[i-1][j-1]+1;
else f[i][j]=max(f[i-1][j],f[i][j-1]);
ans=f[n][m];
for(int i=1;i<=n;++i)
for(int j=0;j<26;++j)
fa[i][j]=a[i]!='a'+j?fa[i-1][j]:i;
for(int i=1;i<=m;++i)
for(int j=0;j<26;++j)
fb[i][j]=b[i]!='a'+j?fb[i-1][j]:i;
getPath(n,m,ans);
for(string str : ss) cout << str << endl;
return 0;
}