求两个字符串的 最短的 公共的 非子序列.即该序列不是A的子序列也不是B的子序列

  • 分析

    考虑填答案DP. 设输入字符串分别为 s , t . 答案为 q.

    对于最后的答案, 由于它是最短的, 所以把他删掉最后一位之后, 它或者是 s 的子序列, 或者 是 t 的子序列.
    从空的答案开始.

    如果 q 的第一个位置是0. 那么就会匹配到 s 的第一个0 和 t 的第一个 0.

    否则 q 的第一个位置是1. 那么就会匹配到 s 的第一个1 和 t 的第一个 1.

    然后考虑第二个位置, 如果是 0, 那么就会匹配到下一个0.

    这样一直匹配下去.直到最后匹配到 s 的末尾的后一位, t 的末尾的后一位, 这时候的 q 是 s,t 的公共非子序列.

    最小字典序: 这题还要一个最小字典序. dp 的时候从后往前遍历. . 最后答案即为.

    然后再从 出发, 从前往后, 先看一下能不能从下一个 转移过来, 如果可以就 转移. 否则选 转移. 这样就可以得到最小的字典序l

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 4e3 + 5, INF = 0x3f3f3f3f;
    
    typedef pair<int, int> pii;
    typedef long long LL;
    
    int suf[2][N][2];
    char s[2][N];
    int dp[N][N], ans[N][N], last0, last1;
    int main()
    {
        scanf("%s %s", s[0]+1, s[1]+1);
        int len[2];
        len[0] = strlen(s[0]+1);
        len[1] = strlen(s[1]+1);
        for (int i = 0; i <= 1; i++) { // 预处理0和1的位置
            last0 = last1 = len[i] + 1;
            for (int j = len[i] + 1; j >= 0; j--) {
                suf[i][j][0] = last0;
                suf[i][j][1] = last1;
                if (s[i][j] == '1') last1 = j;
                else last0 = j;
            }
        }
        memset(dp, INF, sizeof(dp));
        dp[len[0] + 1][len[1] + 1] = 0;
        for (int i = len[0] + 1; i >= 0; i--) {
            for (int j = len[1] + 1; j >=0 ; j--) {
                int x, y;
                x = suf[0][i][0]; // 填0
                y = suf[1][j][0];
                if (dp[x][y] + 1 < dp[i][j] || dp[i][j] == dp[x][y] + 1 && ans[x][y] == 1) {
                    ans[x][y] = 0;
                    dp[i][j] = dp[x][y] + 1;
                }
                x = suf[0][i][1];  // 填1
                y = suf[1][j][1];
                if (dp[x][y] + 1 < dp[i][j]) {
                    ans[x][y] = 1;
                    dp[i][j] = dp[x][y] + 1;
                }
            }
        }
        vector<int> aans;
        int x = 0, y = 0;
        for (int i = 1; i <= dp[0][0]; i++) {
            int nx, ny;
            nx = suf[0][x][0];
            ny = suf[1][y][0];
            if (dp[nx][ny] == dp[x][y]-1) {
                x = nx;
                y = ny;
                aans.push_back(0);
                continue;
            }
            nx = suf[0][x][1];
            ny = suf[1][y][1];
            x = nx, y = ny;
            aans.push_back(1);
        }
        for (auto x:aans) printf("%d", x);
        return 0;
    }