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?
InputInput 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.
OutputA single line contains one integer representing the answer.Sample Input
zzzzzfzzzzz
abcdefedcba
abababababab
cdcdcdcdcdcd
Sample Output
6
7
拿题思想:首先这是一个关于将a字符串变成b字符串所需要最少的次数;他告诉我们可以分成多段来进行变换,所以这是一个区间dp的问题;有当a中的字符与b中相同位置的字符相同,那么是可以不用管的,所以用二维dp[][]来解决问题,首先枚举出每一段,然后每一段中字符相同的只需要进行一次变换就可以了,不同的就在进行变换,这样先找出b字符串中需要最少次数来构成,再来与a字符串比较,找出a,b同位置且字符相同的,这样把他们提出区间可以不用考虑。
遇到问题:解这道题时总是超时。
最终解题步骤:
1)套用模板,枚举b数组的各区间,并且进行简单的赋初值;
2)找出动态转移方程来求解构成b数组所需要的给出字母的最少次数,并记录在dp数组中;
3)相当于再一次运用dp来找出与a中不同字符所在的区间,再来求出a字符串变成b字符串所需要的最少次数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int m=100+5;
int dp[m][m];
char a[m],b[m];
int ans[m];
int main(){
while(scanf("%s%s",a+1,b+1)==2){
memset(dp,0,sizeof(dp));
int l=strlen(a+1);
for(int i=1;i<=l;i++)
dp[i][i]=1;
for(int len=2;len<=l;len++)
for(int i=1;i<=l-len+1;i++){
int j=i+len-1;
if(b[i]==b[j])
dp[i][j]=dp[i][j-1];
else dp[i][j]=dp[i][j-1]+1;
for(int k=i;k<j;k++){
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
}
}
for(int i=1;i<=l;i++) //再一次运用dp;
ans[i]=dp[1][i];
for(int i=1;i<=l;i++){
if(a[i]==b[i])
ans[i]=ans[i-1];
else {
for(int k=1;k<i;k++)
ans[i]=min(ans[i],ans[k]+dp[k+1][i]);
}
}
printf("%d\n",ans[l]);
}
return 0;
}