POJ1934 Trip 题解

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;
}

猜你喜欢

转载自www.cnblogs.com/wzzyr24/p/12301435.html