题目描述
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
Sample Output 1
4
Sample Input 2
a
aaaaa
2
a aa
a aaa
Sample Output 2
2
Sample Input 3
a
aaaaa
2
a aa
a aaa
Sample Output 3
-1
- 1 ≤ ∣ S ∣ ≤ ∣ T ∣ ≤ 50 1\leq |S|\leq |T|\leq 50 1≤∣S∣≤∣T∣≤50
- 1 ≤ K ≤ 50 1\leq K\leq 50 1≤K≤50
- 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 1≤Ai≤50
- 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=l−1mink−1gj−1,d+fd−1,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<bits/stdc++.h>
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;
}