zoukankan      html  css  js  c++  java
  • 2020杭电多校第二场 L

    Description

    给定两个字符串 (S,T),每个询问会指定 (S) 的一个子串和 (T) 作为两个操作串 (A,B),每次可以选择任意一个字符串插入/删除一个字母,回答使得两个操作串相同的最小代价。(|S| le 10^5, |T| le 20)

    Solution

    插入操作是没用的,于是两个串的距离为 (|A|+|B|-2LCS(A,B))

    预处理 (g[i][j]) 表示 (A[i..n]) 中字符 (j) 最早出现的下标

    对于每个询问,暴力 DP

    (f[i][j]) 表示与 (B[1..i]) 的公共序列长度达到 (j)(A[l..r]) 的最短前缀的长度

    [g[f[i][j]+1][B[i+1]] o f[i+1][j+1] \ f[i][j] o f[i+1][j] ]

    [f[i][j]=min(f[i-1][j], g[f[i-1][j-1]][B[i]]) ]

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 100005;
    
    int n,m,q,s[N],t[N],f[25][25],g[N][30];
    
    void make_g()
    {
        for(int c=0;c<26;c++)
        {
            int i=1,j=1;
            while(i<=n)
            {
                while(s[i]!=c && i<=n) ++i;
                if(s[i]==c) for(;j<=i;j++) g[j][c]=i;
                ++i;
            }
            while(j<=n) for(;j<=n;j++) g[j][c]=n+1;
        }
        for(int c=0;c<26;c++) g[0][c]=g[1][c], g[n+1][c]=g[n+2][c]=n+1;
    }
    
    void solve()
    {
        memset(f,0,sizeof f);
        memset(g,0,sizeof g);
        string ss,tt;
        cin>>ss>>tt;
        n=ss.length();
        m=tt.length();
        memset(s,0,sizeof s);
        memset(t,0,sizeof t);
        for(int i=1;i<=n;i++) s[i]=ss[i-1]-'a';
        for(int i=1;i<=m;i++) t[i]=tt[i-1]-'a';
        make_g();
    
        cin>>q;
        while(q--)
        {
            int l,r;
            cin>>l>>r;
            for(int i=0;i<=m;i++)
            {
                for(int j=0;j<=m;j++)
                {
                    f[i][j]=n+1;
                }
            }
            f[0][0]=l-1;
            for(int i=1;i<=m;i++)
            {
                f[i][0]=f[i-1][0];
                for(int j=1;j<=i;j++)
                {
                    f[i][j]=min(f[i-1][j],g[f[i-1][j-1]+1][t[i]]);
                }
            }
            int ans=0;
            for(int i=1;i<=m;i++)
            {
                if(f[m][i]<=r) ans=i;
            }
            cout<<r-l+1+m-2*ans<<endl;
        }
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        int t;
        cin>>t;
        while(t--)
        {
            solve();
        }
    }
    /*
    1
    qaqaqwqaqaq
    qaqwqaq
    3
    1 7
    2 8
    3 9
    */
    
    
  • 相关阅读:
    apns libcurl
    apns libcurl
    epoll
    epoll
    Linux服务器压测
    Linux服务器压测
    libevent
    libevent
    shell脚本
    shell脚本
  • 原文地址:https://www.cnblogs.com/mollnn/p/13375491.html
Copyright © 2011-2022 走看看