String painter
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1625 Accepted Submission(s): 728
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
Recommend
题意:
给定两个长度相等的只由小写字母组成的字符串s、t,每步可以把一个连续字串刷成相同的字母,问至少需要多少步才能把s变成t。
思路:
想了好久 还是没想出来
一开始的方法是 dp[i][j][k] 表示把S[i,j]刷为k,k=26表示不刷即保持原态,0-25就是刷为'a'+k,复杂度 O(n*n*27*n*27) = 7*10^8果断超时了 然后看题解T^T
先不考虑s,考虑一个空串刷为t需要多少步 这个挺巧妙的 想不到 弱。。
dp[i][j] 表示一个空串刷为t最少的步数 则
dp[i][j] = dp[i+1][j] + (strB[i] == strB[j] ? 0 : 1) 意思是把如果strB[i] == strB[j] ,则刷的时候直接把i..j都刷为相同的
这里要注意的是 dp[i][j] != dp[i-1][j-1] + (strB[i] == strB[j] ? 0 : 1) 因为比如是abba这个结果是0,写为dp[i+1][j]是为了保证中间的字母这两个端点刷的一致 这里是留下了右端点即j来保证
dp[i][j] = min(dp[i+1][k] + dp[k+1][j])(前提strB[i] == strB[k])
这里是留下了右端点即k来保证[i+1, k]这段区间和i、k刷的颜色相同,
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif
#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)
const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));
const int maxn = 100 + 20;
char strA[maxn];
char strB[maxn];
int dp[maxn][maxn];
int f[maxn];
int main() {
while(scanf("%s%s", strA, strB) != EOF) {
int n = strlen(strA);
memset(dp, 0, sizeof(dp));
for(int len=1; len<=n; len++) {
for(int s=0; s+len<=n; s++) {
int e = s + len - 1;
if(len == 1) {
dp[s][e] = 1;
continue;
}
dp[s][e] = dp[s+1][e] + (strB[s] == strB[e] ? 0 : 1);
for(int j=s+1; j<=e; j++) {
if(strB[s] == strB[j]) dp[s][e] = min(dp[s][e], dp[s+1][j]+dp[j+1][e]);
}
}
}
f[0] = strA[0] != strB[0];
for(int i=1; i<n; i++) {
f[i] = dp[0][i];
if(strA[i] == strB[i]) f[i] = min(f[i], f[i-1]);
for(int j=0; j<i; j++) {
f[i] = min(f[i], f[j]+dp[j+1][i]);
}
}
int ans = f[n-1];
printf("%d\n", ans);
}
return 0;
}