题意
给两个串A(1…n)和B(1…m),其中n<=1e5,m<=20。多组询问,每一次询问给一组(l,r)值,问至少经过多少次增减操作使得A(l…r)与B(1…m)相同。
思路
难点一:增操作没有必要
考虑最终相等的串,再考虑某一个位置,如果该位置对应的A串和B串字符均是添加进去的,我们可以更优地去除这个位置的字符,从而使答案更优;如果该位置对应的其中一个串的字符是添加进去的,另外一个没有操作,那么我们可以把这个添加操作改为删除操作。因此,增操作均可以由删操作替代
难点二:ans = |r- l + 1| + |m| - 2lcs(串1,串2);
lcs表示两个串的最长公共子序列(注意是子序列不是子串)
了解lcs后,这个结论自然就得出来了
难点三:如果处理多组询问?
注意到m<=20,所以可以支持
n2操作
我们不妨令
f[i][j]表示B[1...i]与A[l...r]最长公共子序列长度为j的在A中的最小位置ans=∣r−l+1∣+∣m∣−2∗j(其中满足f[m][j]<=r的最大j)
考虑DP转移式子
对于f[i−1][j](j属于0−m)已经确定的状态如何更新f[i][...]很简单,影响f[i][...]状态的只有B[i]的值,所以我们只需要确定B[i]会不会更新f[i][...]即可
f[i][j]=min(f[i][j],f[i−1][j])−−自然传递
if(f[i−1][j−1]...n中存在B[i]且最小位置pos小于等于r)=>f[i][j]=min(f[i][j],pos)−−B[i]影响
难点四:如何在A[1…n]中确定B[1…m]中存在B[i]且最小位置小于等于r
其实这个题解提供的方法比较不错;
c[i][j]表示A[i...n]中字符j的最小下标if(A[i]==j),c[i][j]=i;else,c[i][j]=c[i+1][j]
AC代码