zoukankan      html  css  js  c++  java
  • 2020杭电多校第二场 1012.String Distance

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6774

    题意:给你两个字符串 A,B|A|105,|B|20|A|≤105,|B|≤20,每次询问 A 串的一个子串 A[L]...A[R],问该子串通过插入和删除一个字符的操作变得 和B字符串相等的最少操作数

    思路:设A子串为A,很容易可以发现最小操作数=|A|+|B|-2LCS(A,B)。因为插入操作其实是没有意义的,对于最小操作数来说。

    这个问题就转换成了求子串和一个串的LCS。

    如何求呢?

    我们可以用一个nex数组,nex[i][j]表示在第i个字符后出现j字符的位置。这样就可以方便dp了。

    定义 dp [ i ][ j ] , 其含义为 —— 和B的前 i 个字符 , 匹配了长度为 j 的 LCS 的最短 A 前缀。

    那么有 dp[i][j]=min{dp[i][j],dp[i1][j]}

    dp[i][j]=min{dp[i][j],Next[dp[i1][j1]][B[i]]}

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ull;
    int nex[100010][26],dp[21][26];
    char str[100010],pat[30];
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int N,M;
            scanf("%s",str+1);
            scanf("%s",pat+1);
            N=strlen(str+1);
            M=strlen(pat+1);
            memset(nex,0x3f,sizeof(nex));
            for(int i=N;i>=1;i--)
            {
                for(int j=0;j<26;j++)
                    nex[i-1][j]=nex[i][j];
                nex[i-1][str[i]-'a']=i;
            }
            int q;
            scanf("%d",&q);
            while(q--)
            {
                int L,R;
                scanf("%d%d",&L,&R);
                int ans=0;
                memset(dp,0x3f,sizeof(dp));
                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][j],dp[i-1][j]);
                        if(dp[i-1][j-1]<R)
                            dp[i][j]=min(dp[i][j],nex[dp[i-1][j-1]][pat[i]-'a']);
                    }
                }
                int flag=0;
                for(int i=M;i>=0;i--)
                {
                    for(int j=i;j<=M;j++)
                        if(dp[j][i]<=R) 
                        {
                            ans=i;
                            flag=1;
                            break;
                        }
                    if(flag==1)
                    {
                        break;
                    }
                }
                //printf("ans:%d
    ",ans);
                printf("%d
    ",R-L+1+M-ans*2);
            }
        }
        return 0;
    }
  • 相关阅读:
    个人编写的一个简单的DB类
    Access绝对地址
    sentry cli 上传source map
    自动旋转的饼图(echarts)
    点会转的折线图还带着柱子
    node 自动化工程部署
    SQL 模糊查询
    编写一个将输入复制到输出的程序,并将其中连续的多个空格用一个空格代替。
    configure、make、make install 解释
    Linux学习笔记(实时更新)
  • 原文地址:https://www.cnblogs.com/2462478392Lee/p/13374585.html
Copyright © 2011-2022 走看看