LCS

LCS——经典的 DP 问题,给定两个长度为 $n$ 的排列,试问二者的最长公共子序列。这是经典的区间 DP 问题,

首先考虑朴素做法,定义 $dp[i][j]$ 来表示第一个串的前 $i$ 位,第二个串的前 $j$ 的 $LCS$ 长度,易得状态转移方程:

  • 如果两个序列没有新的相同元素

    $dp[i][j] = \max(dp[i-1][j],dp[i][j-1])$

  • 否则

    $dp[i][j]= \max(dp[i][j],dp[i-1][j-1]+1)$

    时间复杂度 $O(n^2)$ 。

#include <iostream>
using namespace std;
const int maxn = 1e4 + 5;

int a[maxn], b[maxn], f[maxn][maxn];

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) cin >> b[i];
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n; 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);
        }
    }
    cout << f[n][n] << "\n";
    return 0;
}

由于时间复杂度中惨了一份平方,所以说在大多数题目下都不适用,此时考虑进行优化。试着将 $LCS$ 问题转换成 $LIS$ 问题,因为我们两个排列,而排列中的所有元素均不相同,因此可以根据其出现的位置,把元素重新编号。

解释:

因为最长公共子序列是按位向后比对的,所以a序列每个元素在b序列中的位置如果递增,就说明b中的这个数在a中的这个数整体位置偏后

—— 离散小波变换

时间复杂度 $O(n \log n)$。

#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = (a), stOwxc = (b); i <= stOwxc; i++)
#define per(i, a, b) for (int i = (a), stOwxc = (b); i >= stOwxc; i--)
using namespace std;
typedef long long ll;

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, x;
    cin >> n;
    unordered_map<int, int> mp;
    rep(i, 1, n) cin >> x, mp[x] = i;
    vector<int> L;
    rep(i, 1, n) {
        cin >> x;
        if (!mp.count(x))
            continue;
        int s = mp[x];
        auto it = lower_bound(L.begin(), L.end(), s);
        if (it == L.end())
            L.push_back(s);
        else
            *it = s;
    }
    cout << L.size() << '\n';
    return 0;
}

注意:

  • map 的常数稍大,可以考虑 unordered_map 来解决问题,在洛谷模板题中,后者比前者快了 $50\%$ 。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇