与编辑距离思想类似,但是编辑距离每次只能增删改。还涉及到字符串的对齐问题。http://blog.youkuaiyun.com/vsooda/article/details/8313172
而本题每次修改就修改一个区间。自然地,使用dp[i][j]表示从i 到 j 所需要的修改次数的上界。
初始化dp[i][j]为dp[i+1][j] + 1
如果s2[i] == s2[k] dp[i][j] = min(dp[i][j], dp[i+1][k] + dp[k+1][j]) 因为i 和 k相同 所以i 和 k可以在一次区间染色操作完成,不再需要对i另外计算。 由于有了区间染色,所以,i 到j被划分成了 i+1 到k k+1 到j 。而且两个子区间都已经被计算过。
使用ans[i]表示到达 i 的所需要的最小染色次数。使用类似dij的算法。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
using namespace std;
#define eps 1e-8
#define pi acos(-1.0)
#define inf 1<<30
#define linf 1LL<<60
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long
string s1,s2;
int minn,len;
int dp[200][200],ans[200];
int main() {
while (cin >> s1){
cin >> s2;
len=s1.size();
memset(dp,0,sizeof(dp));
for (int i=0; i<len; i++) dp[i][i]=1;
for (int j=0; j<len; j++) {
for (int i=j-1; i>=0; i--) {
dp[i][j]=dp[i+1][j]+1;
for (int k=i+1; k<=j; k++) {
if (s2[i]==s2[k]) {
dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]);
}
}
}
}
for (int i=0; i<len; i++) {
ans[i]=dp[0][i];
if (s1[i]==s2[i]) {
if (i==0) ans[i]=0;
else ans[i]=ans[i-1];
}
else {
for (int j=0; j<i; j++)
ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
}
}
printf("%d\n", ans[len-1]);
}
return 0;
}