String painter
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4451 Accepted Submission(s): 2079
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
讲道理,一开始题目都没看懂,以为是一个一个的改变字母。。。真的是被自己蠢到了。根据样例才看懂原来一次性可以改变多个
题意:给出两个字符串ch1和ch2,一次操作能将ch1的一段字符串改变成同一个字符,求把ch1改变成ch2所需要的最少操作数?
今天做这道题的历程就是,好不容易搞懂题意,然后又不知道该怎么做了……看了半天想到是区间dp,刷串的时候,被刷的串的第一个字符和最后一个字符必须相同,不然就是没有意义的(理解一下),但是怎么从ch1变成ch2呢?又没有思路了。。。纠结了半天去找了一下题解,这道题的解题方法真的是贼机智,首先把一个空串变成字符串ch2,
用dp[i][j]记录从空串变成ch2,然后再考虑从串ch1变成ch2,具体还是看代码吧,感觉自己语言表达能力太弱了。。。
#include<iostream>
#include<stdio.h>
#include<string>
#include<math.h>
#include<queue>
#include<vector>
#include<string.h>
#include<iterator>
using namespace std;
typedef unsigned long long ll;
int main()
{
char ch1[105] , ch2[105];
int dp[105][105];
int ans[105];
while(~scanf("%s" , ch1)){
scanf("%s" , ch2);
int n = strlen(ch1);
//cout<<ch1<<endl<<ch2<<endl;
//cout<<n<<endl;
memset(dp , 0 , sizeof(dp));
for(int i = 0 ; i <= n ; i ++)
dp[i][i] = 1;
for(int len = 1 ; len < n ; len ++){//循环区间长度
for(int i = 0 ; i < n - len ; i ++){//枚举起点
int j = i + len ;//终点
dp[i][j] = dp[i + 1][j] + (ch2[i] == ch2[j]?0 : 1 );//初始化,起点与终点相同才有必要刷串
for(int k = i + 1 ; k < j ; k ++){//枚举中间点
if(ch2[i] == ch2[k])
dp[i][j] = min(dp[i][j] , dp[i + 1][k] + dp[k+1][j]);
}
}
}
//cout<<dp[0][n-1]<<"..."<<endl;
for(int i = 0 ; i < n ; i ++){
ans[i] = dp[0][i];
if(ch1[i] == ch2[i])//相同的话就没必要刷
ans[i] = ans[i - 1];
for(int j = 0 ; j < i ; j ++){
ans[i] = min(ans[i] , ans[j] + dp[j + 1][i]);
}
}
cout<<ans[n-1]<<endl;
}
return 0;
}