题目:
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.
Output
A single line contains one integer representing the answer.
Sample Input
zzzzzfzzzzz abcdefedcba abababababab cdcdcdcdcdcd
Sample Output
6 7
题意:输入两个长度相等的字符串A, B, 对A串进行操作使其变成B串, 每次可对A串的某一段就行操作将其变成同一字符, 求变成B串的最小操作次数。
题解:还是很容易想到区间DP的, 对每段的更改操作就是对区间的操作, 直接对A的操作是很难想的, 不如dp[i][j]直接求一个空串变成B串的最小次数, 有了dp值之后再用ans[i]记录下0 ~ i的初始串到目标串的更改次数, ans[i]枚举出所有情况即可。
dp[i][j] = dp[i + 1][j] + (str2[i] == str2[j] ? 0 : 1)为初始化条件, 当i j相等时dp值是1.
AC代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int i, j, n ,ans[105], len, k;
int dp[105][105];
char str1[105], str2[105];
while(~scanf("%s%s", str1, str2)){
n = strlen(str1);
for(len = 1;len <= n;len++){//区间长度
for(i = 0;i < n - len + 1;i++){//区间起点
j = len + i - 1;//区间终点
if(len == 1)
dp[i][i] = 1;//单一点初始化为1
else dp[i][j] = dp[i + 1][j] + (str2[i] == str2[j] ? 0 : 1);//相同时可以一同改掉,不同时次数++
for(k = i + 1;k < j;k++)//枚举分割点
if(str2[i] == str2[k])//字符相同时进行状态转移
dp[i][j] = min(dp[i][j], dp[i + 1][k] + dp[k + 1][j]);
}
}
for(i = 0;i < n;i++){
ans[i] = dp[0][i];//初始化ans[i]
if(str1[i] == str2[i])
ans[i] = ans[i - 1];//字符相同是可以不转化
for(j = 0;j < i;j++)
ans[i] = min(ans[i], ans[j] + dp[j + 1][i]);//枚举所有情况找最小值
}
printf("%d\n", ans[n - 1]);
}
return 0;
}