【2020模拟赛day9】C. 公共序列

【2020模拟赛day9】C. 公共序列

 

 【2020模拟赛day9】C. 公共序列

 

 【2020模拟赛day9】C. 公共序列

 

 

 

正常的LCS问题,时间复杂度是O(|A|*|B|)

但是这道题有一个特点:B串的长度很短,小于等于1000

所以可以换一个状态记录:f[i][j]为A串匹配到第i位,最长公共子序列长度为j的最靠左的B串的位置

为了递推这个方程,需要预处理一个nxt[i][j]表示当前B串在i位置,下一个匹配到j的位置

这样时间复杂度就是O(|A|)

 

代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 1010, inf = 0x7ffffff;
int f[maxn][maxn], nextt[100010][30], n, m, ans;
char a[1010], b[100010];

int main()
{
    freopen("lcs.in","r",stdin);
    freopen("lcs.out","w",stdout);
    scanf("%s%s", a, b);
    n = strlen(a);
    m = strlen(b);
    for (int i = 0; i <= n; i++)
        for (int j = 0; j <= n; j++)
            f[i][j] = inf;
    for (int i = 0; i < 26; i++)
        nextt[m][i] = inf;
    for (int i = m - 1; i >= 0; i--)
    {
        memcpy(nextt[i], nextt[i + 1], sizeof(nextt[i]));
        nextt[i][b[i] - 'a'] = i;
    }
    f[0][1] = nextt[0][a[0] - 'a'];
    for (int i = 0; i <= n; i++)
        f[i][0] = -1;
    for (int i = 0; i < n - 1; i++)
        for (int j = 0; j <= n && f[i][j] < inf; j++)
        {
            f[i + 1][j] = min(f[i + 1][j], f[i][j]);
            if (j < n)
                f[i + 1][j + 1] = min(f[i + 1][j + 1], nextt[f[i][j] + 1][a[i + 1] - 'a']);
        }
    for (int i = n; i >= 1; i--)
        if (f[n - 1][i] != inf)
        {
            ans = i;
            break;
        }
    printf("%d\n", ans);
    return 0;
}

 

上一篇:Day9


下一篇:day9-函数作业