31. 字符串的最大价值(第二期模拟笔试)
题目描述
给定一个字符串 S(S.length < 10000),只包含 0 和 1 两个数字,下标从 1 开始,设第 i 位的价值为 vali,则vali的定义如下:
当 i = 1 时:val1 = 1;
当 i > 1 时:
若Si != S(i - 1):vali = 1,
若Si == S(i - 1):vali = val(i - 1) + 1;
字符串 S 的总价值等于 val1 + val2 + … + valn(n为字符串 S 的长度)。
你可以任意删除字符串 S 中的任意字符,使得字符串 S 的总价值能够达到最大。
输入
输入只有一行,为字符串 S
输出
输出一个整数代表答案
样例输入
010101
样例输出
7
提示
提示
删除一些字符后,S变为 0001 或 0111 时能够达到最大价值。
题解1(C++版本)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e4 + 3; //测试数据的范围超过5000了
int n, cnt0, cnt1;
int start0, end0; //start0,end0分别表示字符'0'在字符串s中第一个,最后一个出现的位置
int start1, end1; //start1,end1分别表示字符'0'在字符串s中第一个,最后一个出现的位置
char s[N];
LL Max(LL a, LL b){
return a > b ? a : b;
}
int main(){
scanf("%s", s + 1);
n = strlen(s + 1);
//printf("%d\n", n);
for(int i = 1;i <= n; i++){
if(s[i] == '0') {
cnt0 = cnt0 + 1;
if(!start0){
start0 = i;
}
end0 = i;
}
else {
cnt1 = cnt1 + 1;
if(!start1){
start1 = i;
}
end1 = i;
}
}
LL sum0 = 0; //统计最长长度的连续0的个数的价值
//首项为1,尾项为(start0 - 1),项数为(start0 - 1)的等差数列求和
sum0 += (1LL + start0 - 1LL)*(start0 - 1LL)/2;
//首项为1,尾项为cnt0,项数为cnt0的等差数列求和
sum0 += (1LL + cnt0) * cnt0/2;
//首项为1,尾项为(n - end0),项数为(n - end0)的等差数列求和
sum0 += (1LL + (n - end0))*(n - end0)/2;
LL sum1 = 0; //统计最长长度的连续1的个数的价值
//首项为1,尾项为(start1 - 1),项数为(start1 - 1)的等差数列求和
sum1 += (1LL + start1 - 1LL)*(start1 - 1LL)/2;
//首项为1,尾项为cnt1,项数为cnt1的等差数列求和
sum1 += (1LL + cnt1) * cnt1/2;
//首项为1,尾项为(n - end1),项数为(n - end1)的等差数列求和
sum1 += (1LL + (n - end1))*(n - end1)/2;
printf("%lld\n", Max(sum0, sum1));
return 0;
}