#P3679. 第1题-多多的神秘字符串
-
1000ms
Tried: 101
Accepted: 56
Difficulty: 2
所属公司 :
拼多多
时间 :2025年9月14日
-
算法标签>字符串
第1题-多多的神秘字符串
思路
让我们来分析一下字符串 a 和 b 之间的关系。
假设原始字符串 a 为 a0a1a2...an−1。 那么,长度为 2 的子串依次是:
- a0a1
- a1a2
- a2a3
- ...
- an−2an−1
字符串 b 就是将这些子串拼接起来的结果: $b = a_0a_1 + a_1a_2 + a_2a_3 + ... + a_{n-2}a_{n-1}$
现在我们来观察字符串 b 的结构:
- b 的前两个字符 b[0],b[1] 就是 a 的第一个子串 a0,a1。所以,我们立刻知道 a0=b[0] 并且 a1=b[1]。
- b 的第三和第四个字符 b[2],b[3] 是 a 的第二个子串 a1,a2。我们已经知道 a1=b[1],所以我们可以推断出 a2=b[3]。(在这个构造过程中,b[2] 必须等于 b[1],因为它们都等于 a1,但我们只需要 b[3] 来获得 a 的下一个新字符)。
- b 的第五和第六个字符 b[4]b[5] 是 a 的第三个子串 a2a3。我们刚推断出 a2=b[3],所以 a3=b[5]。
通过这个分析,我们发现了一个规律:
- 原始字符串 a 的第一个字符是 b[0]。
- a 的其余字符依次是 b[1], b[3], b[5], b[7], ... 也就是 b 中所有索引为奇数的字符。
所以,还原字符串 a 的算法非常简单:
- 取字符串 b 的第一个字符 b[0] 作为 a 的开头。
- 然后,遍历字符串 b 中所有索引为奇数的位置(1,3,5,...),将这些位置上的字符依次拼接到 a 的末尾。
C++
#include <iostream>
#include <string>
#include <vector>
void solve() {
// 读取输入的字符串 b
std::string b;
std::cin >> b;
// 创建一个用于存储结果字符串 a 的变量
std::string a = "";
// 字符串 a 的第一个字符就是 b 的第一个字符
a += b[0];
// 从索引 1 开始,以步长 2 遍历字符串 b
// 这会依次访问 b[1], b[3], b[5], ...
for (int i = 1; i < b.length(); i += 2) {
// 将 b 中奇数索引的字符追加到 a 的末尾
a += b[i];
}
// 输出还原后的字符串 a
std::cout << a << std::endl;
}
int main() {
// 为了加速C++的IO操作
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
// 如果有多个测试用例,可以取消下面的注释
// int t;
// std::cin >> t;
// while (t--) {
// solve();
// }
// 单个测试用例
solve();
return 0;
}
Python
def solve():
"""
读取字符串 b 并还原出字符串 a
"""
# 读取输入的字符串 b
b = input()
# Python 的字符串切片功能非常强大,可以很简洁地解决这个问题。
# b[0] 是 b 的第一个字符。
# b[1::2] 是一个切片操作,表示:
# - 从索引 1 开始
# - 一直取到字符串末尾
# - 步长为 2
# 这会提取出所有索引为奇数的字符: b[1], b[3], b[5], ...
a = b[0] + b[1::2]
# 输出还原后的字符串 a
print(a)
# 调用函数执行
solve()
# 如果有多个测试用例,可以使用循环
# t = int(input())
# for _ in range(t):
# solve()
Java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 创建 Scanner 对象以读取输入
Scanner sc = new Scanner(System.in);
// 读取输入的字符串 b
String b = sc.next();
// 使用 StringBuilder 来高效地构建字符串 a
// 因为在循环中拼接字符串时,StringBuilder比直接使用+操作符性能更好
StringBuilder a = new StringBuilder();
// 字符串 a 的第一个字符就是 b 的第一个字符
a.append(b.charAt(0));
// 从索引 1 开始,以步长 2 遍历字符串 b
// 这会依次访问 b.charAt(1), b.charAt(3), b.charAt(5), ...
for (int i = 1; i < b.length(); i += 2) {
// 将 b 中奇数索引的字符追加到 StringBuilder 的末尾
a.append(b.charAt(i));
}
// 将 StringBuilder 转换为 String 并输出
System.out.println(a.toString());
// 关闭 Scanner
sc.close();
}
// 如果有多个测试用例,可以将逻辑封装在方法中
public static void solve(Scanner sc) {
String b = sc.next();
StringBuilder a = new StringBuilder();
a.append(b.charAt(0));
for (int i = 1; i < b.length(); i += 2) {
a.append(b.charAt(i));
}
System.out.println(a.toString());
}
// 多测试用例的主函数示例
/*
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while (t-- > 0) {
solve(sc);
}
sc.close();
}
*/
}
题目内容
多多在纸上写下了一个由小写英文字母组成的神秘字符串 a ,字符串最小长度为 2 。 然后他从字符串 a 构建出一个新的字符串 b ,从 a 构建 b 的过程如下:
-
按从左到右的顺序写出字符串 a 的所有长度为 2 的子串。
-
将这些字串按相同顺序连接成字符串 b
现在将字符串 b 提供给你,让你猜出神秘字符串 a 是什么。
输入描述
输入仅一行,通过神秘字符串构建出的 b
输出描述
输出仅一行, 为纸上写下的神秘字符串 a
样例1
输入
abbaac
输出
abac
说明
神秘字符串为 "abac" , 那么它的子串是 "ab"、"ba"、"ac”,连接后得到字符串"abbaac"。
样例2
输入
bccddaaf
输出
bcdaf
说明
神秘字符串为 "bcdaf” ,那么它的子串是 "bc","cd","da","af",连接后得到字符串 "bccddaaf"。