题目
hdu2476
题意:
给出字符串a和字符串b,你可以将字符串a的字符段更改为所需的任何其他字符。 输出字符串a更改为字符串b的最少次数。
更改操作:举个例子,在字符串 qwer 中,可以在字符段[0, 2](即字符段qwe)更改为字符 z,即 qwer → zzzr
思路:
可以拆成两步,第一步是把空串更改为字符串b,第二步是根据第一步的结果推导出字符串a更改为字符串b
空串更改为字符串b:
在区间 i ~ j 内,
如果字符串b [ i ] 在 区间 i+1 ~ j 内没有相同的字符,则
d p [ i ] [ j ] = d p [ i + 1 ] [ j ] + 1 dp [ i ] [ j ] = dp [ i + 1 ] [ j ] + 1 dp[i][j]=dp[i+1][j]+1
如果字符串b [ i ] 在 区间 i+1 ~ j 内有相同的字符,则
d p [ i ] [ j ] = min k = i + 1 j d p [ i + 1 ] [ k ] + d p [ k + 1 ] [ j ] dp[i][j] = \min_{k=i+1}^{j} dp[i+1][k] + dp[k+1][j] dp[i][j]=k=i+1minjdp[i+1][k]+dp[k+1][j]
字符串a更改为字符串b:
一开始,ans [ j ] = dp [ 0 ] [ j ],ans [ 0 ] = (a [ 0 ] == b [ 0 ] ) ? 0 : 1;
在区间 0 ~ j 内,
如果字符串a [ j ] = b [ j ],则
a n s [ j ] = a n s [ j − 1 ] ans[j]=ans[j-1] ans[j]=ans[j−1]
如果字符串a [ i ] != b [ i ],则
a n s [ j ] = min k = 0 j a n s [ k ] + d p [ k + 1 ] [ j ] ans[j] = \min_{k=0}^{j} ans[k] + dp[k+1][j] ans[j]=k=0minjans[k]+dp[k+1][j]
as:accc 更改为 abbb 最少要改 1 次(从空串更改为 abbb 则要改 2 次)
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#define DEBUG freopen("_in.txt", "r", stdin); freopen("_out1.txt", "w", stdout);
using namespace std;
const int MAXN = 110;
char a[MAXN], b[MAXN];
int dp[MAXN][MAXN], ans[MAXN];
int , s[MAXN][MAXN], v[200]; //s[i][j]:用二进制来保存字符串b在[i,j]的字符种类,v:记录 a ~ z 的二进制状态
void init(){
for (int i = 0; i < 26; i++)
v[i+'a'] = 1 << i; //a:1, b:10, c:100...
}
void solve(){
if (strcmp(a, b) == 0){
printf("0\n");
return;
}
int lena = strlen(a);
for (int i = 0; i < lena; i++){
dp[i][i] = 1;
s[i][i] = v[b[i]];
}
for (int len = 1; len < lena; len++)
for (int i = 0; i < lena - len; i++){
int j = i + len;
dp[i][j] = dp[i+1][j] + 1;
if ((s[i+1][j] >> (b[i] - 'a')) & 1) //字符串b[i] 在 区间 i+1 ~ j 内有相同的字符
for (int k = i + 1; k <= j; k++)
if (b[i] == b[k])
dp[i][j] = min(dp[i][j], dp[i+1][k] + dp[k+1][j]);
s[i][j] = s[i+1][j] | v[b[i]]; //更新状态
}
for (int i = 0; i < lena; i++)
ans[i] = dp[0][i];
ans[0] = (a[0] == b[0]) ? 0 : 1;
for (int j = 1; j < lena; i++)
if (a[j] == b[j])
ans[j] = ans[j-1];
else
for (int k = 0; k <= j; k++)
ans[j] = min(ans[j], ans[k] + dp[k+1][j]);
printf("%d\n", ans[lena-1]);
}
int main(){
init();
while (~scanf("%s%s", a, b))
solve();
return 0;
}