小QwQ 在批改作业的时候发现大家的提交的文件名都很不规范,这让他很头疼。作为一个强迫症患者,他决定手动规范大家的文件名。但是有些人的文件名特别长,他想要知道最少需要修改多少次才能够使得字符串 A 变成字符串 B 。当然对于修改代价超过 K 的文件名我们会选择放弃。
定义一次修改:
在第 i 个位置插入一个字符
删除第 i 个位置的字符
输出共包含1行,如果最小修改次数小于等于 KK ,则输出最少修改次数,不然输出 -1。
看完题目就可以想到一道题目——编辑距离
但这个比编辑距离少一个操作,因此可以延续到这一题
50pts
O ( n m ) O(nm) O(nm)
转移方程
f
[
i
]
[
j
]
=
m
i
n
(
f
[
i
−
1
]
[
j
]
+
1
,
f
[
i
]
[
j
−
1
]
+
1
)
f[i][j]=min(f[i-1][j] +1,f[i][j-1]+1)
f[i][j]=min(f[i−1][j]+1,f[i][j−1]+1)
f
[
i
]
[
j
]
=
f
[
i
−
1
]
[
j
−
1
]
(
a
[
i
]
=
=
b
[
j
]
)
f[i][j]=f[i-1][j-1](a[i]==b[j])
f[i][j]=f[i−1][j−1](a[i]==b[j])
for(int i=1;i<=len1;i++)
for(int j=1;j<=len2;j++)
{
if(c1[i]==c2[j])dp[i][j]=dp[i-1][j-1];
dp[i][j]=min(dp[i][j],min(dp[i-1][j],dp[i][j-1])+1);
}
if(dp[len1][len2]>k)cout<<-1;
else cout<<dp[len1][len2];
}
else cout<<-1;
return 0;
}
100pts
可以看到k的值是很小的
所以
O
(
n
k
)
O(nk)
O(nk)
可以过这道题目
发现和这个长度相差k多时,这个状态肯定是没有用的,输出-1
所以设
f
[
i
]
[
k
]
为
第
1
串
长
度
为
i
,
第
二
串
和
其
相
差
k
长
度
f[i][k]为 第1串长度为i,第二串和其相差k长度
f[i][k]为第1串长度为i,第二串和其相差k长度
i
f
(
c
1
[
i
]
=
=
c
2
[
j
]
)
d
p
[
i
]
[
w
]
=
m
i
n
(
d
p
[
i
]
[
w
]
,
d
p
[
i
−
1
]
[
w
]
)
;
if(c1[i]==c2[j])dp[i][w]=min(dp[i][w],dp[i-1][w]);
if(c1[i]==c2[j])dp[i][w]=min(dp[i][w],dp[i−1][w]);
d
p
[
i
]
[
w
]
=
m
i
n
(
d
p
[
i
]
[
w
]
,
m
i
n
(
d
p
[
i
−
1
]
[
w
+
1
]
,
d
p
[
i
]
[
w
−
1
]
)
+
1
)
;
dp[i][w]=min(dp[i][w],min(dp[i-1][w+1],dp[i][w-1])+1);
dp[i][w]=min(dp[i][w],min(dp[i−1][w+1],dp[i][w−1])+1);
初始化
f
o
r
(
i
n
t
i
=
0
;
i
<
=
k
;
i
+
+
)
d
p
[
0
]
[
i
]
=
k
−
i
;
for(int i=0;i<=k;i++)dp[0][i]=k-i;
for(inti=0;i<=k;i++)dp[0][i]=k−i;
f
o
r
(
i
n
t
i
=
k
;
i
<
=
k
∗
2
;
i
+
+
)
d
p
[
0
]
[
i
]
=
i
−
k
;
for(int i=k;i<=k*2;i++)dp[0][i]=i-k;
for(inti=k;i<=k∗2;i++)dp[0][i]=i−k;
#include<bits/stdc++.h>
#define maxn 500010
using namespace std;
inline int read()
{
int res=0,f=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch)){res=(res<<1)+(res<<3)+(ch&15);ch=getchar();}
return res*f;
}
int k;
int len1,len2;
char c1[maxn],c2[maxn];
int dp[maxn][210];
int main()
{
len1=read();len2=read();k=read();
memset(dp,63,sizeof(dp));
for(int i=1;i<=len1;i++)cin>>c1[i];
for(int i=1;i<=len2;i++)cin>>c2[i];
for(int i=0;i<=k;i++)dp[0][i]=k-i;// longer i than 0 's val
for(int i=k;i<=k*2;i++)dp[0][i]=i-k;// shorter i-k than 0's val
for(int i=1;i<=len1;i++)
{
for(int j=max(i-k,1);j<=min(i+k,len2);j++)
{
int w=j-i+k;
if(c1[i]==c2[j])dp[i][w]=min(dp[i][w],dp[i-1][w]);
dp[i][w]=min(dp[i][w],min(dp[i-1][w+1],dp[i][w-1])+1);
}
}
if(dp[len1][len2-len1+k]>k)cout<<-1;
else cout<<dp[len1][len2-len1+k];
return 0;
}