C++ 中的回文划分 III
假设我们有一个字符串 s,其中包含小写字母和一个整数 k。我们必须维护一些属性。这些是 -
- 首先,我们必须更改 s 的某些字符(如果需要)为其他小写英文字母。
- 然后将字符串 s 分割成 k 个子字符串,使得每个子字符串都是回文。
我们必须找到我们需要更改的字符的最小数量以分割字符串。
因此,如果字符串类似于“ababbc”且 k = 2,则答案将为 1,因为我们必须更改一个字符才能将其分成两个回文字符串。因此,如果我们将 c 更改为 b,或将倒数第二个 b 更改为 c,那么我们可以得到一个回文,例如“bbb”或“cbc”,另一个回文是“aba”。
为了解决这个问题,我们将遵循以下步骤 -
- 定义一个大小为 105 x 105 的数组 memo。
- 定义一个函数 solve(),它将接收 s、idx、k、一个二维数组 > dp,
- 如果 idx 与 s 的大小相同,则 -
- 返回当 k 为 0 时为 0,否则为 1000
- 如果 memo[idx][k] 不等于 -1,则 -
- 返回 memo[idx][k]
- 如果 k <= 0,则 -
- 返回 inf
- ans := inf
- 对于初始化 i := idx,当 i < s 的大小时,更新(i 增加 1),执行 -
- ans := ans 和 dp[idx][i] + 调用函数 solve(s, i + 1, k - 1, dp) 的最小值
- 返回 memo[idx][k] = ans
- 从主方法中执行以下操作
- n := s 的大小
- 用 -1 填充 memo
- 定义一个大小为 n x n 的二维数组 dp
- 对于初始化 l := 2,当 l <= n 时,更新(l 增加 1),执行 -
- 对于初始化 i := 0,j := l - 1,当 j < n 时,更新(j 增加 1),(i 增加 1),执行 -
- 如果 l 等于 2,则 -
- 当 s[i] 不等于 s[j] 时,dp[i][j] := true
- 否则
- 当 s[i] 等于 s[j] 时,dp[i][j] := dp[i + 1][j - 1] + 0
- 对于初始化 i := 0,j := l - 1,当 j < n 时,更新(j 增加 1),(i 增加 1),执行 -
- 返回 solve(s, 0, k, dp)
让我们看看以下实现以获得更好的理解 -
示例
#include <bits/stdc++.h> using namespace std; typedef long long int lli; class Solution { public: int memo[105][105]; lli solve(string s, int idx, int k, vector < vector <int> > &dp){ if(idx == s.size()) { return k == 0? 0 : 1000; } if(memo[idx][k] != -1) return memo[idx][k]; if(k <= 0)return INT_MAX; lli ans = INT_MAX; for(int i = idx; i < s.size(); i++){ ans = min(ans, dp[idx][i] + solve(s, i + 1, k - 1, dp)); } return memo[idx][k] = ans; } int palindromePartition(string s, int k) { int n = s.size(); memset(memo, -1, sizeof(memo)); vector < vector <int> > dp(n, vector <int>(n)); for(int l =2; l <= n; l++){ for(int i = 0, j = l - 1; j <n; j++, i++){ if(l==2){ dp[i][j] = !(s[i] == s[j]); }else{ dp[i][j] = dp[i+1][j-1] + !(s[i] == s[j]); } } } return solve(s, 0, k, dp); } }; main(){ Solution ob; cout << (ob.palindromePartition("ababbc", 2)); }
输入
“ababbc”
输出
1
广告