题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6774
题目大意:
对于操作:删除一个字符或者添加一个字符
给你两个字符串A,B。q次询问,每次询问A串的A[l...r]最少通过多少次操作变成B。
思路:通过序列自动机得到一个数组:net[i][j]:A[i-]后面第一个j字符的位置。
然后每次一个DP:f[i][j]:B前i个字符匹配了j个字符的子序列的最近位置。
转移:
我们推导出:最少操作次数=r-l+m-*LCS
#include<bits/stdc++.h>
using namespace std;
char a[2000005], b[105];
int nxt[2000005][26];
int n, m;
int main() {
int t;
scanf("%d", &t);
while(t--) {
scanf("%s%s",a+1, b+1);
n=strlen(a+1), m=strlen(b+1);
for(int i=n+5; i>=0; i--) {
for(int j=0; j<26; j++) {
nxt[i][j]=0;
}
}
for(int i=n; i>=1; i--) {
for(int j=0; j<26; j++) {
nxt[i-1][j]=nxt[i][j];
}
nxt[i-1][a[i]-'a'] = i;
}
int q;
scanf("%d", &q);
while(q--) {
int l, r;
scanf("%d%d", &l, &r);
int mx=0;
int f[25][25];
memset(f, 0x3f, sizeof(f));
f[0][0]=l-1;
for(int i=1; i<=m; i++){
for(int j=0; j<=i; j++){
f[i][j]=f[i-1][j];
if(j>=1&&f[i-1][j-1]!=f[23][23]){
f[i][j]=min(f[i][j], (nxt[f[i-1][j-1]][b[i]-'a']==0)?f[23][23]:nxt[f[i-1][j-1]][b[i]-'a']);
}
if(f[i][j]<=r){
mx=j;
}
}
}
printf("%d\n",r-l+1-2*mx+m);
}
}
}

京公网安备 11010502036488号