• AtcoderABC261 G Replace


    AtcoderABC261

    题目描述

    You are given two strings S S S and T T T consisting of lowercase English letters.
    Takahashi starts with the string S S S.He can perform K K K kinds of operations any number of times in any order.
    The i i i-th operation is the following:

    • Pay a cost of 1 1 1,if the current string contains the character C i C_i Ci,choose one of its occurrences and replace it with the string A i A_i Ai,Otherwise,do nothing.
      Find the minimum total cost needed to make the string equal T T T.If it is impossible to do so,print − 1 -1 1.
    Sample Input 1
    ab
    cbca
    3
    a b
    b ca
    a efg
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    Sample Output 1
    4
    
    • 1
    Sample Input 2
    a
    aaaaa
    2
    a aa
    a aaa
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    Sample Output 2
    2
    
    • 1
    Sample Input 3
    a
    aaaaa
    2
    a aa
    a aaa
    
    • 1
    • 2
    • 3
    • 4
    • 5
    Sample Output 3
    -1
    
    • 1
    • 1 ≤ ∣ S ∣ ≤ ∣ T ∣ ≤ 50 1\leq |S|\leq |T|\leq 50 1ST50
    • 1 ≤ K ≤ 50 1\leq K\leq 50 1K50
    • C i C_i Ci is a , b , … , a,b,\dots, a,b,, or z z z.
    • 1 ≤ A i ≤ 50 1\leq A_i\leq 50 1Ai50
    • S , T S,T S,T and A i A_i Ai are strings consisting of lowercase English letters.
    • C i ≠ A i C_i\neq A_i Ci=Ai,regarding C i C_i Ci as a string of length 1 1 1.
    • All pairs ( C i , A i ) (C_i,A_i) (Ci,Ai) are distinct.

    题目大意

    给两个字符串 S S S T T T,都由小写字母组成。高桥以字符串 S S S开始,他可以执行以下 K K K种操作任意多次,可以按任意顺序。第 i i i种操作如下:

    • 花费 1 1 1元,如果当前字符串包含字符 C i C_i Ci,选择其中一处 C i C_i Ci,将它替换为 A i A_i Ai,否则什么也不做。

    求从字符串 S S S到字符串 T T T所需要的最少花费。如果无法做到,输出 − 1 -1 1

    题解

    这是一道区间DP的题。设 f i , j , c f_{i,j,c} fi,j,c表示字符 c c c替换为 t t t [ i , j ] [i,j] [i,j]的最小步数。我们可以先用替换后长度增加的更新,再用替换后长度不变的更新,来保证转移的正确性。

    先处理替换后长度增加的状态更新。对于每个操作,设 g j , k g_{j,k} gj,k表示把当前 A A A [ 1 , j ] [1,j] [1,j]替换成 t t t [ l , k ] [l,k] [l,k]的最小步数。则转移式为

    g j , k = min ⁡ d = l − 1 k − 1 g j − 1 , d + f d − 1 , k , A j g_{j,k}=\min\limits_{d=l-1}^{k-1} g_{j-1,d}+f_{d-1,k,A_j} gj,k=d=l1mink1gj1,d+fd1,k,Aj

    然后再处理替换后长度不变的状态更新。用Floyd预处理从字符串 i i i替换成字符串 j j j的最小步数 g t i , j gt_{i,j} gti,j,则转移式为

    f i , j , c = m i n ( g t c , c ′ + f i , j , c ′ ) f_{i,j,c}=min(gt_{c,c'}+f_{i,j,c'}) fi,j,c=min(gtc,c+fi,j,c)

    求答案时也是类似,就相当于把 S S S当作一个操作来处理。

    虽然看上去是 O ( n 6 ) O(n^6) O(n6)的,但是经过一顿计算之后得出是可以过的。

    code

    #include
    using namespace std;
    int s1,t1,k,inf=0x3f3f3f3f,p[55][55][55],z[2][55],gt[55][55];
    char s[55],t[55];
    struct node{
        int a1;
        char c,a[55];
    }w[55];
    int main()
    {
        scanf("%s%s",s+1,t+1);
        s1=strlen(s+1);
        t1=strlen(t+1);
        memset(gt,0x3f,sizeof(gt));
        memset(p,0x3f,sizeof(p));
        scanf("%d",&k);
        for(int i=1;i<=k;i++){
            w[i].c=getchar();
            while(w[i].c<'a'||w[i].c>'z') w[i].c=getchar();
            scanf("%s",w[i].a+1);
            w[i].a1=strlen(w[i].a+1);
            if(w[i].a1==1) gt[w[i].a[1]-'a'][w[i].c-'a']=1;
        }
        for(int d=0;d<=25;d++){
            for(int i=0;i<=25;i++){
                for(int j=0;j<=25;j++){
                    gt[i][j]=min(gt[i][j],gt[i][d]+gt[d][j]);
                }
            }
        }
        for(int i=1;i<=t1;i++){
            p[i][i][t[i]-'a']=0;
        }
        for(int len=1;len<=t1;len++){
            for(int i=1;i+len-1<=t1;i++){
                int j=i+len-1;
                for(int o=1;o<=k;o++){
                    if(w[o].a1>len) continue;
                    for(int g=i-1;g<=j;g++) z[0][g]=z[1][g]=inf;
                    z[0][i-1]=0;
                    bool fl=1,e;
                    for(int g=1;g<=w[o].a1;g++){
                        bool ys=0;e=g&1;
                        z[e][i-1]=inf;
                        for(int d1=i;d1<=j;d1++){
                            z[e][d1]=inf;
                            for(int d2=i-1;d2<d1;d2++){
                                z[e][d1]=min(z[e][d1],z[e^1][d2]+p[d2+1][d1][w[o].a[g]-'a']);
                            }
                            if(z[e][d1]<inf) ys=1;
                        }
                        if(!ys){
                            fl=0;break;
                        }
                    }
                    if(fl){
                        p[i][j][w[o].c-'a']=min(p[i][j][w[o].c-'a'],z[e][j]+1);
                    }
                }
                for(int p1=0;p1<=25;p1++){
                    for(int p2=0;p2<=25;p2++){
                        p[i][j][p1]=min(p[i][j][p1],p[i][j][p2]+gt[p2][p1]);
                    }
                }
            }
        }
        memset(z,0x3f,sizeof(z));
        z[0][0]=0;
        bool e;
        for(int i=1;i<=s1;i++){
            e=i&1;
            for(int j=0;j<=t1;j++){
                z[e][j]=inf;
                for(int d=1;d<=j;d++){
                    z[e][j]=min(z[e][j],z[e^1][d-1]+p[d][j][s[i]-'a']);
                }
            }
        }
        if(z[e][t1]>=inf) printf("-1");
        else printf("%d",z[e][t1]);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
  • 相关阅读:
    神经网络图怎么分析,画神经网络结构图
    模型运行过程中占内存的中间变量
    医护上门系统—为老人和患者提供更舒适和现代化体验
    LeetCode(Python)—— Excel表列名称(简单)
    转行软件测试两个多月,感觉很迷茫,下一步该如何提高自己?
    数据库开发-MySQL基础DQL和多表设计
    Redis笔记基础篇:6分钟看完Redis的八种数据类型
    Qt使用QSettings类来读写ini
    C++标准模板(STL)- 输入/输出操纵符-(std::setprecision,std::setw)
    可重复执行SQL语句|建表、插入默认值、增加字段、删除字段、修改字段可重复执行SQL语句|oracle|mysql
  • 原文地址:https://blog.csdn.net/tanjunming2020/article/details/126858233