Shortest Common Non-Subsequence

题目链接:https://ac.nowcoder.com/acm/contest/7831/D

题意:给出两个 01 串 a 和 b,求最短的 01 串 t ,使得 t 不是 a 和 b 的子序列,若有多个答案则输出字典序最小的。

思路:先用自动序列预处理下,然后再dfs记录即可。

a 串 [x,lena]区间 和 b 串[y,lenb]区间的最优解可能性分两种,

0 + [ a[x][0] , lena ]区间和[ b[x][0] , lenb ]区间的最优解;

1 + [a[x][1] , lena]区间和[b[x][1] , lenb]区间的最优解;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char a[4005],b[4005];
int lena,lenb;
int dp[4005][4005],f[4005][4005];
int nexa[4005][2],nexb[4005][2];
vector<int> ans;
int dfs(int x,int y)
{
    if(x==lena+1&&y==lenb+1)
        return 0;
    if(dp[x][y])
        return dp[x][y];
    int tmp0=dfs(nexa[x][0],nexb[y][0]);
    int tmp1=dfs(nexa[x][1],nexb[y][1]);
    if(tmp0<=tmp1)
        f[x][y]=0;
    else
        f[x][y]=1;
    dp[x][y]=min(tmp0,tmp1)+1;
    return dp[x][y];
}
void fun(int x,int y)
{
    if(x==lena+1&&y==lenb+1)
        return;
    int tmp=f[x][y];
    ans.push_back(tmp);
    fun(nexa[x][tmp],nexb[y][tmp]);
}
int main()
{
    scanf("%s",a+1);
    scanf("%s",b+1);
    lena=strlen(a+1);
    lenb=strlen(b+1);
    nexa[lena+1][0]=nexa[lena+1][1]=lena+1;
    nexb[lenb+1][0]=nexb[lenb+1][1]=lenb+1;
    for(int i=lena;i>=0;i--)
    {
        nexa[i][0]=nexa[i+1][0];
        nexa[i][1]=nexa[i+1][1];
        if(a[i+1]=='0')
            nexa[i][0]=i+1;
        else
            nexa[i][1]=i+1;
    }
    for(int i=lenb;i>=0;i--)
    {
        nexb[i][0]=nexb[i+1][0];
        nexb[i][1]=nexb[i+1][1];
        if(b[i+1]=='0')
            nexb[i][0]=i+1;
        else
            nexb[i][1]=i+1;
    }
    dfs(0,0);
    fun(0,0);
    for(int i=0;i<ans.size();i++)
        cout<<ans[i];
    cout<<endl;
}

 

posted @ 2020-10-05 17:53  ~zcb  阅读(189)  评论(0编辑  收藏  举报