2023-09-07:用go语言编写。塔子哥最近在处理一些字符串相关的任务

他喜欢 R 字符,因为在某些任务中,这个字符通常表示“正确”的结果

另一方面,他不喜欢 B 字符,因为在某些任务中,这个字符通常表示“错误”的结果

为了解决他的任务,塔子哥定义了字符串的权值为字符串中 R 字符的出现次数

例如,对于字符串 BBRBRB,它的权值为 2,因为其中有 2 个 R 字符

现在,塔子哥面临一个问题,他有一个长度为 n 的字符串 s,它仅由 R 和 B 组成

他想知道,长度为 n 的仅由 R 和 B组成的字符串中,

字典序不小于 s 的字符串的权值之和是多少?

因此,他需要编写一个程序来解决这个问题

输入第一行为一个整数 n ,表示字符串的长度

输入第二行为一个长度为 n 的字符串 s ,字符串中元素组成仅为 R 和 B

输出一个整数,代表长度为 n 的、字典序不小于 s 的字符串权值之和。

输入样例:

3

RBR

输出:

7

解释:共有 3 个字符串字典序大于等于"RBR",RBR权值为2,RRB为2,RRR为3。

1 <= n <= 100000,

结果可能很大,对1000000007取模。

来自左程云

答案2023-09-07:

大体过程如下:

算法一(sum1):

1.定义函数sum1,它接收一个字符串作为参数,并返回字典序不小于该字符串的所有可能字符串中权值之和。

2.在sum1中,定义了辅助函数process1,它通过递归生成所有可能的字符串,并计算符合条件的字符串的权值之和。

3.在process1中,递归地生成新字符串,每次添加'R'或'B',直到生成的字符串长度与给定字符串长度相等。

4.如果生成的字符串与给定字符串相等或更大,返回权值之和,其中权值为'R'的个数。

5.如果生成的字符串小于给定字符串,返回0,表示没有符合条件的字符串。

6.在每个递归步骤中,将递归调用的结果相加,计算出所有可能字符串的权值之和。

7.在sum1函数中,调用process1函数并返回最终的权值之和。

算法二(sum3):

1.定义函数sum3,它接受一个字符串作为参数,并返回字典序不小于该字符串的所有可能字符串的权值之和。

2.在sum3中,首先初始化一些辅助数组和变量。

3.使用动态规划的方法来计算权值之和。

4.创建一个长度为n+1的dp数组,其中dp[i]表示以第i个字符作为起始字符的后缀字符串的权值之和。

5.初始化dp[n]为给定字符串最后一个字符的权值。

6.从右到左遍历字符串,计算dp数组的值。

7.如果当前字符是'R',根据公式计算p1和p2,然后将p1和p2相加得到dp[i]。

8.如果当前字符是'B',将dp[i+1]的值赋给dp[i]。

9.最后返回dp[0]作为最终的权值之和。

时间复杂度:

  • 算法一(sum1)的时间复杂度为O(2^n),其中n是给定字符串的长度。因为它通过递归的方式生成所有可能的字符串。

  • 算法二(sum3)的时间复杂度为O(n),其中n是给定字符串的长度。因为它使用动态规划计算权值之和。

额外空间复杂度:

  • 算法一(sum1)的额外空间复杂度为O(n),因为递归调用process1函数可能会使用到O(n)的栈空间。

  • 算法二(sum3)的额外空间复杂度为O(n),因为它使用了dp数组来存储中间结果,数组长度为n+1。

go完整代码如下:

package main

import (
"fmt"
"math/rand"
"strings"
"time"
) const MAXN = 100001
const mod = 1000000007 var pow2, f [MAXN]int func sum1(str string) int {
return process1("", str)
} func process1(path, s string) int {
if len(path) == len(s) {
if strings.Compare(path, s) >= 0 {
ans := 0
for i := 0; i < len(path); i++ {
if path[i] == 'R' {
ans++
}
}
return ans
} else {
return 0
}
} else {
return process1(path+"R", s) + process1(path+"B", s)
}
} func initialize() {
pow2[0] = 1
for i := 1; i < MAXN; i++ {
pow2[i] = (pow2[i-1] * 2) % mod
}
f[1] = 1
for i := 2; i < MAXN; i++ {
f[i] = (pow2[i-1] + f[i-1]) % mod
f[i] = (f[i] + f[i-1]) % mod
}
} func sum2(str string) int {
n := len(str)
s := []byte(str)
rnumber := make([]int, n)
rnumber[0] = map[bool]int{true: 1, false: 0}[s[0] == 'R']
for i := 1; i < n; i++ {
rnumber[i] = rnumber[i-1] + map[bool]int{true: 1, false: 0}[s[i] == 'R']
}
return process2(s, rnumber, n, 0)
} func process2(s []byte, rnumber []int, n, i int) int {
var ans int
if i == n {
ans = rnumber[n-1]
} else {
if s[i] == 'B' {
p1 := int(((int64(rnumber[i]+1)*int64(pow2[n-i-1]))%int64(mod) + int64(f[n-i-1])) % int64(mod))
p2 := process2(s, rnumber, n, i+1)
ans = (p1 + p2) % mod
} else {
ans = process2(s, rnumber, n, i+1)
}
}
return ans
} func sum3(str string) int {
n := len(str)
s := []byte(str)
rnumber := make([]int, n)
rnumber[0] = map[bool]int{true: 1, false: 0}[s[0] == 'R']
for i := 1; i < n; i++ {
rnumber[i] = rnumber[i-1] + map[bool]int{true: 1, false: 0}[s[i] == 'R']
}
dp := make([]int, n+1)
dp[n] = rnumber[n-1]
for i := n - 1; i >= 0; i-- {
if s[i] == 'B' {
p1 := int(((int64(rnumber[i]+1)*int64(pow2[n-i-1]))%int64(mod) + int64(f[n-i-1])) % int64(mod))
p2 := dp[i+1]
dp[i] = (p1 + p2) % mod
} else {
dp[i] = dp[i+1]
}
}
return dp[0]
} func randomString(n int) string {
s := make([]byte, n)
for i := 0; i < n; i++ {
if rand.Float32() < 0.5 {
s[i] = 'B'
} else {
s[i] = 'R'
}
}
return string(s)
} func main() {
rand.Seed(time.Now().UnixMilli())
N := 15
testTimes := 10000
fmt.Println("测试开始")
initialize()
for i := 0; i < testTimes; i++ {
n := rand.Intn(N) + 1
s := randomString(n)
ans1 := sum1(s)
ans3 := sum3(s)
if ans1 != ans3 {
fmt.Println("出错了!")
}
}
fmt.Println("测试结束")
}

c++完整代码如下:

#include <iostream>
#include <vector>
#include <string>
#include <random> constexpr int MAXN = 100001;
constexpr int mod = 1000000007; std::vector<int> pow2(MAXN);
std::vector<int> f(MAXN); int process1(const std::string& path, const std::string& s); int sum1(const std::string& str) {
return process1("", str);
} int process1(const std::string& path, const std::string& s) {
if (path.length() == s.length()) {
if (path.compare(s) >= 0) {
int ans = 0;
for (int i = 0; i < path.length(); i++) {
if (path[i] == 'R') {
ans++;
}
}
return ans;
}
else {
return 0;
}
}
else {
return process1(path + "R", s) + process1(path + "B", s);
}
} void initialize() {
pow2[0] = 1;
for (int i = 1; i < MAXN; i++) {
pow2[i] = (pow2[i - 1] * 2) % mod;
}
f[1] = 1;
for (int i = 2; i < MAXN; i++) {
f[i] = (pow2[i - 1] + f[i - 1]) % mod;
f[i] = (f[i] + f[i - 1]) % mod;
}
} int process2(const std::vector<char>& s, const std::vector<int>& rnumber, int n, int i); int sum2(const std::string& str) {
int n = str.length();
std::vector<char> s(str.begin(), str.end());
std::vector<int> rnumber(n);
rnumber[0] = (s[0] == 'R') ? 1 : 0;
for (int i = 1; i < n; i++) {
rnumber[i] = rnumber[i - 1] + ((s[i] == 'R') ? 1 : 0);
}
return process2(s, rnumber, n, 0);
} int process2(const std::vector<char>& s, const std::vector<int>& rnumber, int n, int i) {
int ans;
if (i == n) {
ans = rnumber[n - 1];
}
else {
if (s[i] == 'B') {
int p1 = (((int64_t)(rnumber[i] + 1) * (int64_t)pow2[n - i - 1]) % (int64_t)mod + (int64_t)f[n - i - 1]) % (int64_t)mod;
int p2 = process2(s, rnumber, n, i + 1);
ans = (p1 + p2) % mod;
}
else {
ans = process2(s, rnumber, n, i + 1);
}
}
return ans;
} int sum3(const std::string& str) {
int n = str.length();
std::vector<char> s(str.begin(), str.end());
std::vector<int> rnumber(n);
rnumber[0] = (s[0] == 'R') ? 1 : 0;
for (int i = 1; i < n; i++) {
rnumber[i] = rnumber[i - 1] + ((s[i] == 'R') ? 1 : 0);
}
std::vector<int> dp(n + 1);
dp[n] = rnumber[n - 1];
for (int i = n - 1; i >= 0; i--) {
if (s[i] == 'B') {
int p1 = (((int64_t)(rnumber[i] + 1) * (int64_t)pow2[n - i - 1]) % (int64_t)mod + (int64_t)f[n - i - 1]) % (int64_t)mod;
int p2 = dp[i + 1];
dp[i] = (p1 + p2) % mod;
}
else {
dp[i] = dp[i + 1];
}
}
return dp[0];
} std::string randomString(int n) {
std::string s(n, ' ');
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 1);
for (int i = 0; i < n; i++) {
if (dis(gen) < 0.5) {
s[i] = 'B';
}
else {
s[i] = 'R';
}
}
return s;
} int main() {
std::random_device rd;
std::mt19937 gen(rd());
int N = 15;
int testTimes = 100;
std::cout << "测试开始" << std::endl;
initialize();
for (int i = 0; i < testTimes; i++) {
int n = gen() % N + 1;
std::string s = randomString(n);
int ans1 = sum1(s);
int ans3 = sum3(s);
if (ans1 != ans3) {
std::cout << "出错了!" << std::endl;
}
}
std::cout << "测试结束" << std::endl;
return 0;
}

2023-09-07:用go语言编写。塔子哥最近在处理一些字符串相关的任务 他喜欢 R 字符,因为在某些任务中,这个字符通常表示“正确”的结果 另一方面,他不喜欢 B 字符,因为在某些任务中,这个字符的更多相关文章

  1. Java语言编写MD5加密方法,Jmeter如何给字符串MD5加密

    package md5package; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; ...

  2. 运用Python语言编写获取Linux基本系统信息(三):Python与数据库编程,把获取的信息存入数据库

    运用Python语言编写获取Linux基本系统信息(三):Python与数据库编程 有关前两篇的链接: 运用Python语言编写获取Linux基本系统信息(一):获得Linux版本.内核.当前时间 运 ...

  3. Fastjson是一个Java语言编写的高性能功能完善的JSON库。

    简介 Fastjson是一个Java语言编写的高性能功能完善的JSON库. 高性能 fastjson采用独创的算法,将parse的速度提升到极致,超过所有json库,包括曾经号称最快的jackson. ...

  4. Leaf - 一个由 Go 语言编写的开发效率和执行效率并重的开源游戏服务器框架

    转自:https://toutiao.io/posts/0l7l7n/preview Leaf 游戏服务器框架简介 Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏 ...

  5. 如何用C语言编写病毒‘

    怎样用C语言编写病毒在分析病毒机理的基础上,用C语言写了一个小病毒作为实例,用TURBOC2.0实现.[Abstract] This paper introduce the charateristic ...

  6. 用C语言编写一个简单的词法分析程序

    问题描述: 用C或C++语言编写一个简单的词法分析程序,扫描C语言小子集的源程序,根据给定的词法规则,识别单词,填写相应的表.如果产生词法错误,则显示错误信息.位置,并试图从错误中恢复.简单的恢复方法 ...

  7. 【操作系统】C语言编写的FAT16文件系统

    [操作系统]C语言编写的FAT16文件系统 这是操作系统的期末课程设计作业之一,主要功能是在物理内存中虚拟出一个1M大小的FAT16的文件系统,然后把它读入内存中,进行具体的文件操作,具体的实用性不大 ...

  8. 第二次作业利用java语言编写计算器进行四则运算

    随着第一次作业的完成,助教 牛老师又布置了第二次作业:用java语言编写一个程序然后进行四则运算用户用键盘输入一个字符来结束程序显示统计结果.一开始看到这个题目我也着实吓了一跳 因为不知道如何下手而且 ...

  9. PHP语言编写的磁力搜索工具下载BT种子 支持transmission、qBittorrent

    磁力搜索网站2020/01/12更新 https://www.cnblogs.com/cilisousuo/p/12099547.html PT种子.BT种子搜索功能 IYUU自动辅种工具,目前能对国 ...

  10. 基于php基础语言编写的小程序之计算器

    基于php基础语言编写的小程序之计算器 需求:在输入框中输入数字进行加.减.乘.除运算(html+php) 思路: 1首先要创建输入数字和运算符的输入框,数字用input的text属性,运算符用sel ...

随机推荐

  1. Vue2系列(lqz)——Vue生命期钩子、组件

    文章目录 Vue声明期钩子 组件 1 fetch和axios 1.1 fetche使用 1.2 axios的使用 2 计算属性 2.1 通过计算属性实现名字首字母大写 2.2 通过计算属性重写过滤案例 ...

  2. LVS+keepalived配置高可用架构和负载均衡机制(1)

    一.基础知识 1. 四层负载均衡(基于IP+端口的负载均衡) 所谓四层负载均衡,也就是主要通过报文中的目标ip地址和端口,再加上负载均衡设备设置的服务器选择方式(分发策略,轮询),决定最终选择的内部服 ...

  3. .NET周刊【10月第1期 2023-10-01】

    国内文章 .NET应用如何防止被反编译 https://www.cnblogs.com/Can-daydayup/p/17736700.html 本文主要讲述了如何防止.NET应用被反编译.虽然无法完 ...

  4. 2023 版 Java和python开发线性代数探索

    目录 前景提示 需求 分析 1.初始化不需要指定矩阵的尺寸,并且可以直接传入数据. 2.可以计算2x2矩阵的逆 3.可以做2x2的矩阵乘法 Java版本开发 一. 开发详情 1.开发一个子类,如图所示 ...

  5. 堆优化模拟退火(List-Based Simulated Annealing|List-Based SA|LBSA|模拟退火) 算法

    图炸了的话请多刷新几次(upd:8.9) 堆优化模拟退火(List-Based Simulated Annealing) 算法 引入 堆优化模拟退火(List-Based Simulated Anne ...

  6. Codeforces Round 823 (Div. 2)C

    C. Minimum Notation 思路:我们可以进行的操作时将一个位置的数删除然后在任意位置处添加一个比当前数大1并且小于9的数,所以我们的操作只会让一个数变大,我们统计一个最大值的后缀,贪心的 ...

  7. 「Eolink Apikit 教程」API 异常监控-创建 API 监控

    API 监控能够确保 API 的稳定性.如果一个 API 出现故障或崩溃,它可能会导致整个应用程序无法正常工作.这对用户和业务来说可能是灾难性的.通过监控 API,开发团队可以及时发现问题并采取措施来 ...

  8. P1126 机器人搬重物 题解

    Problem 题目概括 $n \times m $ 的网格,有些格子是障碍格.\(0\) 无障碍,\(1\) 有障碍.机器人有体积,总是在格点上. 有5种操作: 向前移动 \(1/2/3\) 步 左 ...

  9. AttributeError: module 'sqlalchemy' has no attribute '__all__'

    升级组件 pip install --upgrade flask-sqlalchemy

  10. [C++]P5024 树形DP 保卫王国

    树形DP 保卫王国P5024 前置知识 1.邻接表 + Dfs(深度优先搜索) 2.基础DP(如 01背包 ) 3.最小公共祖先(LCA) LCA我有写过Blog 首先解读一下题意 城市即为节点 每个 ...