• [2020杭电多校第二场]1012 String Distance(lcs)


    不难发现答案即为a[l, r]的长度加上b的长度减去2倍的a[l,r]与b的LCS。

    那么难点就在于如何处理出每次询问的lcs了,这里仍然采用dp的思想。对于dp[i][j]代表b串前i个字符串与a[l,r]形成了长度为j的公共子序列时在a串中的最小下标位置。

    那么不难得出转移方程1 :dp[i][j] = min(dp[i][j], dp[i+1][j]) 和 转移方程2:dp[i][j] = min(dp[i][j], a串中dp[i-1][j-1]后面第一个出现b[i]的位置),而某个位置后面第一个字符出现的位置显然可以用序列自动机直接得出。那么这样子复杂度就是26*n + q * m * m,你就可以快乐的ac了。具体实现见代码。

    #pragma GCC optimize("-Ofast","-funroll-all-loops")
    //freopen("C://std/a.in","r",stdin);
    //freopen("C://std/b.txt","w",stdout);
    #include<bits/stdc++.h>
    #define ll long long
    #define PB push_back
    #define endl '
    '
    #define INF 0x3f3f3f3f
    #define LINF 0x3f3f3f3f3f3f3f3f
    #define ull unsigned long long
    #define lson rt << 1, l, mid
    #define rson rt << 1 | 1, mid + 1, r
    #define lowbit(x) (x & (-x))
    #define rep(i, a, b) for(int i = a ; i <= b ; ++ i)
    #define per(i, a, b) for(int i = b ; i >= a ; -- i)
    #define clr(a, b) memset(a, b, sizeof(a))
    #define in insert
    #define random(x) (rand()%x)
    #define PII(x, y) make_pair(x, y)
    #define fi first
    #define se second
    #define pi acos(-1)
    #define re register
    //std::ios::sync_with_stdio(false);
    using namespace std;
    const int maxn = 1e6 + 50;
    const int N = 1e5 + 10;
    const int M = N * 20;
    const ll mod = 1e9 + 9;
    int T, n, m;
    int nxt[maxn][26], dp[30][30];
    char a[maxn], b[maxn];
    int solve(int l, int r){
        clr(dp, INF); dp[0][0] = l - 1;
        for(int i = 1 ; i <= m ; ++ i){
            dp[i][0] = l - 1;
            for(int j = 1 ; j <= i ; ++ j){
                dp[i][j] = min(dp[i-1][j],dp[i][j]);
                if(dp[i-1][j-1] < r)
                dp[i][j] = min(dp[i][j], nxt[dp[i-1][j-1]][b[i]-'a']);
            }
        }
        per(i, 0, m){
            rep(j, i, m){
                if(dp[j][i] <= r) return i;
            }
        }
        return 0;
    }
    signed main(){
        cin >> T; int q, l, r;
        while(T --){
            scanf("%s", a + 1); n = strlen(a + 1);
            scanf("%s", b + 1); m = strlen(b + 1);
            scanf("%d", &q);
            clr(nxt, 0x3f);
            per(i, 1, n){
                for(int j = 0 ; j < 26 ; ++ j){
                    nxt[i-1][j] = nxt[i][j];
                }
                nxt[i-1][a[i]-'a'] = i;
            }
            while(q --){
                scanf("%d %d", &l, &r);
                cout << r - l + 1 + m - solve(l, r) *  2 << endl;
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Hadoop 启动脚本分析与实战经验
    mac appium-Andriod sdk安装
    windows解决appium-doctor报gst-launch-1.0.exe and/or gst-inspect-1.0.exe cannot be found
    windows解决appium-doctor报opencv4nodejs cannot be found
    windows解决appium-doctor报 mjpeg-consumer cannot be found.
    windows解决appium-doctor报ffmpeg cannot be found问题
    windows解决appium-doctor报 bundletool.jar cannot be found
    内存分配和垃圾回收调优
    内存分配与回收策略
    JVM老年代和新生代的比例
  • 原文地址:https://www.cnblogs.com/Ketchum/p/13375772.html
Copyright © 2020-2023  润新知