bzoj4275 [ONTAK2015]Badania naukowe

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4275

【题解】

考虑预处理出来a[1..i]和b[1..j]的LCS,记为$f_{i,j}$;a[i..n]和b[j..m]的LCS,记为$g_{i,j}$。

同时预处理出来如果从a[i]开始匹配c串,终止位置,记为$af_i$;同理记录$bf_i$。

那么枚举c串在A,B中开始的位置$i$和$j$,就有贡献为$f_{i-1,j-1} + |c| + g_{af_i+1, bf_i+1}$

直接做即可,复杂度$O(nm)$。

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N = 3e3 + 10;
const int mod = 1e9+7;

int n, m, K;
int a[N], b[N], c[N];

int f[N][N], g[N][N], af[N], bf[N];

int main() {
    cin >> n; for (int i=1; i<=n; ++i) scanf("%d", a+i);
    cin >> m; for (int i=1; i<=m; ++i) scanf("%d", b+i);
    cin >> K; for (int i=1; i<=K; ++i) scanf("%d", c+i);
    for (int i=1; i<=n; ++i)
        for (int j=1; j<=m; ++j) {
            f[i][j] = max(f[i-1][j], f[i][j-1]);
            if(a[i] == b[j]) f[i][j] = max(f[i][j], f[i-1][j-1] + 1);
        }
    for (int i=n; i; --i)
        for (int j=m; j; --j) {
            g[i][j] = max(g[i+1][j], g[i][j+1]);
            if(a[i] == b[j]) g[i][j] = max(g[i][j], g[i+1][j+1] + 1);
        }
    if(!K) {
        cout << f[n][m] << endl;
        return 0;
    }
    for (int i=1; i<=n; ++i) {
        int k = 0;
        af[i] = n+1;
        for (int j=i; j<=n; ++j) {
            if(a[j] == c[k+1]) ++k;
            if(k == K) {
                af[i] = j;
                break;
            }
        }
    }
    for (int i=1; i<=m; ++i) {
        int k = 0;
        bf[i] = m+1;
        for (int j=i; j<=m; ++j) {
            if(b[j] == c[k+1]) ++k;
            if(k == K) {
                bf[i] = j;
                break;
            }
        }    
    }
//    for (int i=1; i<=n; ++i) cout << af[i] << ' '; cout << endl;
//    for (int i=1; i<=m; ++i) cout << bf[i] << ' '; cout << endl;
    int ans = -1;
    for (int i=1, ii, jj; i<=n; ++i)
        for (int j=1; j<=m; ++j) {
            ii = af[i], jj = bf[j];
            if(ii == n+1 || jj == m+1) continue;
            ans = max(ans, f[i-1][j-1] + g[ii+1][jj+1] + K);
        }
    cout << ans;
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/galaxies/p/bzoj4275.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值