小美的01串翻转

小美定义一个 01 串的权值为:每次操作选择一位取反,使得相邻字符都不相等的最小操作次数。
例如,"10001"的权值是 1,因为只需要修改一次:对第三个字符取反即可。
现在小美拿到了一个 01 串,她希望你求出所有非空连续子串的权值之和,你能帮帮她吗?

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 256M,其他语言512M

输入描述:

 

一个仅包含'0'和'1'的字符串,长度不超过 2000。

输出描述:

 

所有非空子串的权值和。

示例1

输入例子:

10001

输出例子:

8

例子说明:

 

长度为 2 的子串中,有 2 个"00"的权值是 1。

长度为 3 的 3 个子串权值都是 1。

长度为 4 的 2 个子串权值都是 1。

长度为 5 的 1 个子串权值是 1。

总权值之和为 2+3+2+1=8

可以使用动态规划来解决。

首先,定义一个二维数组 dp,其中 dp[i][j] 表示从第 i 个字符到第 j 个字符(包含两端)的子串的权值和。

对于每个字符 s[j],我们可以分两种情况讨论:

  1. 如果 s[j] 和 s[j-1] 相等,说明当前字符不需要取反,那么 dp[i][j] = dp[i][j-1];
  2. 如果 s[j] 和 s[j-1] 不相等,说明当前字符需要取反,那么 dp[i][j] = dp[i][j-1] + 1。

最终的答案就是 dp[0][n-1],其中 n 是字符串 s 的长度。

下面是具体的实现代码:

cpp

1#include <bits/stdc++.h>
2using namespace std;
3const int N = 2005;
4int n;
5char s[N];
6int dp[N][N];
7
8int main() {
9cin >> s+1; // 读入字符串,从第二个字符开始读入
10n = strlen(s+1); // 计算字符串长度
11
12for (int i = 1; i <= n; i++) {
13if (s[i] == s[i-1]) {
14dp[i][i] = dp[i-1][i-1]; // 相等时权值不变
15} else {
16dp[i][i] = dp[i-1][i-1] + 1; // 不相等时权值加一
17}
18for (int j = i+1; j <= n; j++) {
19if (s[j] == s[j-1]) {
20dp[i][j] = dp[i][j-1]; // 相等时权值不变
21} else {
22dp[i][j] = dp[i][j-1] + 1; // 不相等时权值加一
23}
24}
25}
26cout << dp[0][n] << endl; // 输出最终答案
27return 0;
28}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清贫码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值