题目大意:
给出a,b两个串,a串可以分成若干串,问将a的每个分开的串分别转化为b串,最少的操作数是多少
思路:
二分答案,避免超时。
dp[i][j]表示在a串的第i个字符和j串的第j个字符最少的操作数是多少。
那么当a的i + 1个字符和b的j + 1个字符相等时候,它的最小操作数是和a到i个字符和b到j个字符的值是一样的。
那么当a到i个字符和b到j + 1个字符的时候,此时最小的操作数可能是a到i个字符和b到j个字符的值 + 1,不可能是相等的。
那么当a到i + 1个字符和b到j 个字符的时候,道理同上。
代码:
#include <iostream>
using namespace std;
#include <cstring>
#include <stdio.h>
const int INF = 0x3f3f3f3f;
int n,m;
char a[5555],b[555];
int dp[5555][555];
bool check(int mid) {
for(int i = 0; i <= n; i++)
for(int j = 0; j <= m; j++)
dp[i][j] = INF;
dp[0][0] = 0;
for(int i = 0; i <= n; i++) {
if(dp[i][m] <= mid)
dp[i][0] = 0;
for(int j = 0; j <= m; j++) {
if(dp[i][j] > mid)
continue;
dp[i + 1][j + 1] = min(dp[i + 1][j + 1],dp[i][j] + (a[i + 1] == b[j + 1]?0:1));
dp[i][j + 1] = min(dp[i][j + 1],dp[i][j] + 1);
dp[i + 1][j] = min(dp[i + 1][j],dp[i][j] + 1);
}
}
if(dp[n][m] <= mid)
return true;
return false;
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
scanf("%s%s",b+1,a+1);
n = strlen(a + 1);
m = strlen(b + 1);
int l = 0,r = max(n,m);
while(l < r) {
int mid = (l + r)/2;
if(check(mid)) {
r = mid;
}
else
l = mid + 1;
}
printf("%d\n",l);
}
return 0;
}