String painter
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3530 Accepted Submission(s): 1640
Total Submission(s): 3530 Accepted Submission(s): 1640
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
2008 Asia Regional Chengdu
题意:给你两个字符串,求出第一串改成第二串的最小步数,修改的方式是你可以选择任意区间,将其中所有字母修改成同一个字母。
思路:
毫无疑问是区间dp,但是怎么写出表达式是一个很严肃的问题o( ̄▽ ̄)do( ̄▽ ̄)do( ̄▽ ̄)d
由空串修改成第二串这个区间dp还是很好写的,个人觉得下面的那个转化才是神奇。
空串转化第二串,度娘给我的那个确实不错,但是我估计比较笨,想不到那种转化。
当然学习一下还是非常有必要的,说不定什么时候用上了呢。。
这里,当i和k位置字符相同时,有dp[i+1][k]+dp[k+1][j] 取最小,这就是精髓所在了。
看清楚,这里是dp[i+1][k],和dp[i][k]有区别,就这一个区别,顿时不一样了,因为相等,所以i可以和k同刷,即dp[i][k]==dp[i+1][k];
这个dp就很清晰很明了了。
我没想到,所以,自己写了一个搓逼代码,那可真是挫orz
这就是中规中矩的区间dp,毫无创意的搓逼代码。。。对比一下,多余内容好多,就不解释了,只是想证明一下自己的搓逼本质,吐血ing.
最重要的还是下面的由空串如何替换成第一串
代码:
这也是一个牛逼的dp呀。
显而易见的这里只计算从[0,i]的转化。
ans[i]代表的是[0,i]的最小转化步数。
当是s1[i]==s2[i]时,直接等于前一步。
不等的时候,如代码所示。
神奇,神奇,神奇.......
题意:给你两个字符串,求出第一串改成第二串的最小步数,修改的方式是你可以选择任意区间,将其中所有字母修改成同一个字母。
思路:
毫无疑问是区间dp,但是怎么写出表达式是一个很严肃的问题o( ̄▽ ̄)do( ̄▽ ̄)do( ̄▽ ̄)d
由空串修改成第二串这个区间dp还是很好写的,个人觉得下面的那个转化才是神奇。
空串转化第二串,度娘给我的那个确实不错,但是我估计比较笨,想不到那种转化。
当然学习一下还是非常有必要的,说不定什么时候用上了呢。。
for(j = 0; j<len; j++)
{
for(i = j; i>=0; i--)//j为尾,i为头
{
dp[i][j] = dp[i+1][j]+1;//先每个单独刷
for(k = i+1; k<=j; k++)//i到j中间所有的刷法
{
if(s2[i]==s2[k])
dp[i][j] = min(dp[i][j],(dp[i+1][k]+dp[k+1][j]));//i与k相同,寻找i刷到k的最优方案
}
}
}
这里,当i和k位置字符相同时,有dp[i+1][k]+dp[k+1][j] 取最小,这就是精髓所在了。
看清楚,这里是dp[i+1][k],和dp[i][k]有区别,就这一个区别,顿时不一样了,因为相等,所以i可以和k同刷,即dp[i][k]==dp[i+1][k];
这个dp就很清晰很明了了。
我没想到,所以,自己写了一个搓逼代码,那可真是挫orz
for(int len=2;len<=n;len++)
{
for(int l=0;l+len-1<n;l++)
{
int r=l+len-1;
if(s[l]==s[l+1])
dp[l][r]=dp[l+1][r];
else if(s[r]==s[r-1])
dp[l][r]=dp[l][r-1];
else if(s[l]==s[r])
{
dp[l][r]=dp[l+1][r-1]+1;
for(int k=1;k<r;k++)
if(s[l]==s[k])
dp[l][r]=min(dp[l][r],dp[l][k]+dp[k][r]-1);
}
for(int k=l;k<r;k++)
{
dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]);
}
}
}
这就是中规中矩的区间dp,毫无创意的搓逼代码。。。对比一下,多余内容好多,就不解释了,只是想证明一下自己的搓逼本质,吐血ing.
最重要的还是下面的由空串如何替换成第一串
代码:
for(int i=0;i<n;i++)
res[i]=dp[0][i];
for(int i=0;i<n;i++)
{
if(s[i]==s1[i])
{
if(i==0)
res[i]=0;
else
res[i]=res[i-1];
}
else
{
for(int j=0;j<i;j++)
res[i]=min(res[i],res[j]+dp[j+1][i]);
}
}
这也是一个牛逼的dp呀。
显而易见的这里只计算从[0,i]的转化。
ans[i]代表的是[0,i]的最小转化步数。
当是s1[i]==s2[i]时,直接等于前一步。
不等的时候,如代码所示。
神奇,神奇,神奇.......