🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员
✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解
💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导
👏 感谢大家的订阅➕ 和 喜欢💗
📎在线评测链接
https://app5938.acapp.acwing.com.cn/contest/2/problem/OD1088
🌍 评测功能需要 ⇒ 订阅专栏 ⇐ 后私信联系清隆解锁~
🍓OJ题目截图
文章目录
- 📎在线评测链接
- 🍓OJ题目截图
- 🌲 LYA的字符串拼接游戏
- 问题描述
- 输入格式
- 输出格式
- 样例输入
- 样例输出
- 样例解释
- 样例输入
- 样例输出
- 样例解释
- 数据范围
- 题解
- 参考代码
🌲 LYA的字符串拼接游戏
问题描述
LYA最近迷上了一款字符串拼接游戏。游戏规则如下:
给定一个由小写字母组成的字符集合,以及一个正整数 N N N。从字符集合中任意取出字符(每个字符只能用一次),拼接成一个长度为 N N N 的字符串,要求相邻的字符不能相同。
请帮助LYA计算出,给定的字符集合能拼接出多少种满足条件的字符串。如果输入非法或无法拼接出满足条件的字符串,则输出 0 0 0。
输入格式
输入为一行,包含一个由小写字母组成的字符串和一个正整数 N N N,两者之间用一个空格分隔。
- $1 \le $ 字符串长度 ≤ 29 \le 29 ≤29
- 1 ≤ N ≤ 5 1 \le N \le 5 1≤N≤5
输出格式
输出一个整数,表示能拼接出的满足条件的字符串个数。
样例输入
abc 1
样例输出
3
样例解释
给定的字符集合为 abc
,结果字符串长度为 1 1 1,可以拼接出 a
、b
、c
三种字符串,因此输出 3 3 3。
样例输入
dde 2
样例输出
2
样例解释
给定的字符集合为 dde
,结果字符串长度为 2 2 2,可以拼接出 de
、ed
两种字符串,因此输出 2 2 2。
数据范围
- $1 \le $ 字符串长度 ≤ 29 \le 29 ≤29
- 1 ≤ N ≤ 5 1 \le N \le 5 1≤N≤5
题解
本题可以用回溯法(DFS)来解决。
我们定义一个布尔数组 vis
来记录每个字符是否被使用过。然后从字符集合的第一个字符开始,尝试将它加入结果字符串。如果当前字符没有被使用过,且与结果字符串的最后一个字符不同,就将它加入结果字符串,并标记为已使用。
接下来,我们继续尝试从剩余的未使用字符中选择下一个字符,直到结果字符串的长度达到 N N N。如果能够成功构造出一个满足条件的字符串,就将答案加一。
在尝试每一步时,我们都需要跳过重复的字符,以避免重复计算。这可以通过对字符集合进行排序,然后在遍历时跳过连续相同的字符来实现。
时间复杂度为 O ( N ! × M ) O(N! \times M) O(N!×M),其中 N N N 为结果字符串的长度, M M M 为字符集合的长度。空间复杂度为 O ( M ) O(M) O(M),用于存储字符集合和访问数组。
参考代码
- Python
from itertools import permutationsdef count_strings(chars, n):res = 0for perm in permutations(chars, n):if all(perm[i] != perm[i+1] for i in range(n-1)):res += 1return reschars, n = input().split()
n = int(n)
print(count_strings(chars, n))
- Java
import java.util.*;public class Main {static int k;static char[] cs;static int res;static boolean[] vis;static StringBuilder sb = new StringBuilder();static int n;public static void main(String[] args) {Scanner sc = new Scanner(System.in);String s = sc.next();n = s.length();k = sc.nextInt();cs = s.toCharArray();vis = new boolean[n];Arrays.sort(cs);dfs(0);System.out.println(res);}static void dfs(int u) {if (u == k) {res++;return;}for (int i = 0; i < n; i++) {if (vis[i]) {continue;}if (i > 0 && cs[i] == cs[i - 1] && !vis[i - 1]) {continue;}if (sb.length() > 0 && sb.charAt(sb.length() - 1) == cs[i]) {continue;}vis[i] = true;sb.append(cs[i]);dfs(u + 1);sb.deleteCharAt(sb.length() - 1);vis[i] = false;}}
}
- Cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int n, k;
string cs;
int res = 0;
vector<bool> vis;
string sb;void dfs(int u) {if (u == k) {res++;return;}for (int i = 0; i < n; i++) {if (vis[i]) {continue;}if (i > 0 && cs[i] == cs[i - 1] && !vis[i - 1]) {continue;}if (!sb.empty() && sb.back() == cs[i]) {continue;}vis[i] = true;sb.push_back(cs[i]);dfs(u + 1);sb.pop_back();vis[i] = false;}
}int main() {cin >> cs >> k;n = cs.length();vis.resize(n, false);sort(cs.begin(), cs.end());dfs(0);cout << res << endl;return 0;
}