#P2801. 第2题-小苯的字符串
-
1000ms
Tried: 9
Accepted: 3
Difficulty: 6
所属公司 :
阿里
时间 :2025年4月8日-阿里淘天(开发岗)
-
算法标签>构造
第2题-小苯的字符串
题解
题面描述
给定一个正整数n,要求构造一个只由小写英文字母 a 到 z 组成的字符串 s,其中字符串长度为n。
要求满足:对于 s 的所有本质不同的连续子串(即去重后所有相邻字符组成的子串),其中长度为奇数的子串出现次数必须为奇数。
本质不同的连续子串指的是从字符串中提取的所有连续子串中,对内容相同的子串只保留一个。例如,对于字符串 "aa",所有连续子串有 "a"(出现两次)和 "aa",去重后结果为 {"a","aa"}。
思路
-
统计全同字符构造的字符串性质
如果采用全由同一字母构成的字符串,比如 s=an,那么所有本质不同的连续子串为
{a,aa,…,an} 数量正好为 n。在这些子串中,长度为奇数的子串个数为:- 当 n 为奇数时,奇数子串个数为 2n+1;
- 当 n 为偶数时,奇数子串个数为 2n。
因此,要求这些数量为奇数,则当 n≡1 或 2 (mod 4) 时,全a串满足要求。
-
构造满足条件的字符串
对于其他情况我们需要对全a串进行适当修改,使得由修改部分引入的奇数长度子串个数发生奇偶性翻转,从而满足题目要求。- 当 n≡0 (mod 4) 时,可以构造后缀为 "abca"。即令s=a(n−4)+"abca"
- 当 n≡3 (mod 4) 时,可以构造后缀为 "abacaba"(注意 n=3 时单独处理,用 "aba" 即可)。即令s=a(n−7)+"abacaba"
这样通过不同后缀修正,全体字符串中奇数长度子串的个数即可满足奇数条件。
代码分析
下面以 C++ 代码为例进行分析:
- 输入部分:首先读取测试数据组数 T,然后对每组测试数据读取 n 的值。
- 分情况构造字符串:
- 若 n≡1 或 2 (mod 4),直接输出由全字符 'a' 组成的字符串。
- 若 n≡0 (mod 4),则在字符串的末尾加入 "abca",前面补上 n−4 个 'a'。
- 若 n≡3 (mod 4),则在字符串末尾加入 "abacaba",前面补上 n−7 个 'a'(若 n=3 则直接用 "aba")。
- 输出部分:将构造好的字符串输出。
本质上,这种构造方法利用了全a串在连续子串个数上的规律,在需要调整奇数子串个数时,加上特定模式的后缀,将原本偶数变化为奇数,从而满足题意。
C++
#include <iostream>
#include <string>
using namespace std;
int main(){
int T;
cin >> T; // 读入测试数据组数 T
while(T--){
int n;
cin >> n; // 读入字符串长度 n
string s;
int r = n % 4; // 求 n 对 4 取余以判断情况
if(r == 1 || r == 2){
// 当 n ≡ 1 或 2 (mod 4) 时,直接构造全由字符 'a' 组成的字符串
s = string(n, 'a');
} else if(r == 0){
// 当 n ≡ 0 (mod 4) 时,前面填充 n-4 个 'a',后缀为 "abca"
s = string(n - 4, 'a') + "abca";
} else { // r == 3
// 当 n ≡ 3 (mod 4) 时,若 n == 3,则直接用 "aba"
// 若 n >= 7,则前面填充 n-7 个 'a',后缀为 "abacaba"
if(n == 3)
s = "aba";
else
s = string(n - 7, 'a') + "abacaba";
}
cout << s << "\n"; // 输出构造好的字符串
}
return 0;
}
Python
# 读入测试数据组数 T
T = int(input())
for _ in range(T):
# 读入字符串长度 n
n = int(input())
# 初始化结果字符串 s
s = ""
r = n % 4 # 求 n 对 4 取余
if r == 1 or r == 2:
# 当 n ≡ 1 或 2 (mod 4) 时,构造全'a'字符串
s = "a" * n
elif r == 0:
# 当 n ≡ 0 (mod 4) 时,前面填充 n-4 个 'a',后缀为 "abca"
s = "a" * (n - 4) + "abca"
else: # r == 3
if n == 3:
# 当 n 为 3 时,直接使用 "aba"
s = "aba"
else:
# 当 n ≥ 7 且 n ≡ 3 (mod 4) 时,前面填充 n-7 个 'a',后缀为 "abacaba"
s = "a" * (n - 7) + "abacaba"
print(s) # 输出构造好的字符串
Java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 读入测试数据组数 T
int T = in.nextInt();
while (T-- > 0) {
// 读入字符串长度 n
int n = in.nextInt();
String s = "";
int r = n % 4; // 求 n 对 4 取余
if (r == 1 || r == 2) {
// 当 n ≡ 1 或 2 (mod 4) 时,构造全'a'字符串
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.append('a');
}
s = sb.toString();
} else if (r == 0) {
// 当 n ≡ 0 (mod 4) 时,前面填充 n-4 个 'a',后缀为 "abca"
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n - 4; i++) {
sb.append('a');
}
sb.append("abca");
s = sb.toString();
} else { // r == 3
if (n == 3) {
// 当 n 为 3 时,直接使用 "aba"
s = "aba";
} else {
// 当 n ≥ 7 且 n ≡ 3 (mod 4) 时,前面填充 n-7 个 'a',后缀为 "abacaba"
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n - 7; i++) {
sb.append('a');
}
sb.append("abacaba");
s = sb.toString();
}
}
System.out.println(s); // 输出构造好的字符串
}
in.close();
}
}
题目内容
小苯给了你一个正整数n,他希望你构造一个仅包含小写英文字母'a'到'z'的长度为n的字符串s,满足:
s的所有本质不同连续子串中,长度为奇数的子串恰好出现了奇数次。
请你构造一个吧。
本质不同连续子串:指的是从一个字符串中提取的所有连续子串(也就是相邻字符组成的子串)中,按照内容相同性去重后得到的集合。在这个集合中心如果两个子串在字符序列上完全相同,那么它们被视为"本质相同,只记作一个。
例如,对字符串:“aa”。所有可能的连续子串(包括重复的)为:
从位置1:“a",“aa”
从位置2:“a”
其中“a”出现了两次,但本质不同连续子串只记作{“a”,“aa”}两个。
因为重复的“a”只保留一个,
输入描述
本题有多组测试数据
输入的第一石包含一个正预数T(1≤T≤100),表示数据回数,
接下来包含T组数据,每组数据的格式如下
在单独的一行输入一个正整数n(1≤n≤2000)
(保证所有更试数起中,n的总和不超过2000。)
输出描述
对于每时测试数据:
输出一行一个长度为n的字符串,符合题意
样例1
输入
1
4
输出
llve