题目大意:
有一个字符串,我们可以对其任意字符作变更。现在我们想把字符串切成k个回文串,问我们最少需要换多少个字符。
解题思路:
这种区间切割问题,应该需要联想到区间DP,考虑设立状态dp[l][k]表示起始点为l时候还需要划分k个字符时我们需要替换的最少字符数。可以写出伪代码:
for i l->n-1:
dp[l][k]=min(dp[l][k],cost[l][i]+dp[i+1][k-1])
为什么i只能到n-1呢,因为我的边界情况设置为k==1,我们就结束访问,所以我们必须至少留有1个字母给后面分割。
边界情况是k==1还有递归时候自身长度小于k就退出。
class Solution {
public:
string arr;
int n;
const int inf=1e9;
vector<vector<int>> dp;
vector<vector<int>> cost;
int dfs(int l,int k){
if(n-1-l+1<k)return inf;
if(k==1)return dp[l][k]=cost[l][n-1];
if(dp[l][k]!=-1)return dp[l][k];
dp[l][k]=inf;
for(int i=l;i<n-1;i++){
dp[l][k]=min(dp[l][k],cost[l][i]+dfs(i+1,k-1));
}
assert(dp[l][k]<inf);
return dp[l][k];
}
int palindromePartition(string s, int k) {
arr=s;
n=s.size();
cost.assign(n,vector<int>(n));
for(int i=0;i<n;i++)
for(int j=i;j<n;j++){
int tmp=0;
for(int z=0;z<(j-i+1)/2;z++){
if(s[i+z]!=s[j-z])tmp++;
}
cost[i][j]=tmp;
}
dp.assign(n,vector<int>(n+10,-1));;
dfs(0,k);
return dp[0][k];
}
};