String painter,区间dp
String painter
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11069 Accepted Submission(s): 5416
Problem Description
There are two strings A and B with equal length. Both strings are made up of lower case letters. Now you have a powerful string painter. With the help of the painter, you can change a segment of characters of a string to any other character you want. That is, after using the painter, the segment is made up of only one kind of character. Now your task is to change A to B using string painter. What’s the minimum number of operations?
Input
Input contains multiple cases. Each case consists of two lines:
The first line contains string A.
The second line contains string B.
The length of both strings will not be greater than 100.
The first line contains string A.
The second line contains string B.
The length of both strings will not be greater than 100.
Output
A single line contains one integer representing the answer.
Sample Input
zzzzzfzzzzz
abcdefedcba
abababababab
cdcdcdcdcdcd
Sample Output
6
7
Source
解析 :
可以先将一个空串转化成B,再比较与将A直接转化成B那个更快;
子集划分:令dp[i][j]为将[i, j]区间转换成功最少操作数;
最坏的情况下,是将每个字符都变一下,dp[i][i]=1;区间[i, i+1]是由[i, i]扩展来的,dp[i][i+1]=dp[i][i]+1;同理:dp[i][j]=dp[i][j-1]+1;然后在区间[i, j]中如果有一个B[k]==B[j]那么dp[i][j]=min(dp[i][j], dp[i][k-1]+dp[k][j-1]);这一步是如何来的呢?
[i, j]区间可以看作[i, k-1]+[k, j-1],当B[j]==B[k]时,所以先[k, j]全转换成1种字符,再将[k+1, j-1]转换,相当于只转化了[k, j-1];
注意,这里不要写成dp[k+1][j-1]+1, 因为dp[k][j-1]可能更小;
ans[i]表示A的[1, i]区间转换成B的[1, i]的最少操作
ans[i]=min(ans[i], ans[k]+dp[k+1][i])(0<=k<=i);
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
using namespace std;
typedef long long LL;
const int N = 1e2 + 5;
int n;
char a[N], b[N];
int f[N][N],ans[N];
int main() {
while (scanf("%s%s",a+1,b+1)!=EOF) {
n = strlen(a+1);
memset(f, 0, sizeof f);
for (int i = 1; i <= n; i++)
f[i][i] = 1;
for (int len = 2; len <= n; len++) {
for (int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
f[i][j] = f[i][j-1] + 1;
for (int k = i-1; k < j; k++) {
if (b[k] == b[j])
f[i][j] = min(f[i][j], f[i][k-1] + f[k][j - 1]);
}
}
}
for (int i = 1; i <= n; i++) {
ans[i] = f[1][i];
}
for (int i = 1; i <= n; i++) {
if (a[i] == b[i]) {
ans[i] = ans[i - 1];
}
else {
for (int j = 1; j < i; j++) {
ans[i] = min(ans[j] + f[j + 1][i], ans[i]);
}
}
}
cout << ans[n] << endl;
}
return 0;
}