题目描述:
给定 M(0<M<=30)个字符(a-z),从中取出任意字符(每个字符只能用一次)拼接成长度为 N(0<N<=5)的字符串,要求相同的字符不能相邻,计算出给定的字符列表能拼接出多少种满足条件的字符串,输入非法或者无法拼接出满足条件的字符串则返回 0。
输入描述:
给定的字符列表和结果字符串长度,中间使用空格(" ")拼接
输出描述:
满足条件的字符串个数
示例1:
输入
abc 1
输出
3
说明:给定的字符为 a,b,c,结果字符串长度为 1,可以拼接成 a,b,c,共 3 种
示例2:
输入
dde 2
输出
2
说明:给定的字符为 dde,结果字符串长度为 2,可以拼接成 de,ed,共 2 种
C++源码:
#include <iostream>
#include <vector>
#include <string>
#include <unordered_set>
using namespace std;
int countValidStrings(const string& chars, int N) {
if (N > chars.size()) return 0;
vector<vector<int>> dp(N + 1, vector<int>(chars.size() + 1, 0));
unordered_set<char> uniqueChars(chars.begin(), chars.end());
// 初始化
for (int i = 0; i <= chars.size(); ++i) {
dp[1][i] = uniqueChars.size();
}
// 动态规划
for (int len = 2; len <= N; ++len) {
for (int used = 1; used <= chars.size(); ++used) {
// 不使用第 used 个字符的情况
dp[len][used] = dp[len][used - 1];
// 使用第 used 个字符的情况,需要保证前一个字符不是当前字符
if (used >= 2 && chars[used - 2] != chars[used - 1]) {
dp[len][used] += dp[len - 1][used - 2];
}
}
}
return dp[N][chars.size()];
}
int main() {
string input;
getline(cin, input);
if (input.find(' ') == string::npos) {
cout << 0 << endl;
system("pause");
return 0;
}
string chars = input.substr(0, input.find(' '));
int N = stoi(input.substr(input.find(' ') + 1));
if (N <= 0 || N > 5 || chars.size() > 30) {
cout << 0 << endl;
}
else {
cout << countValidStrings(chars, N) << endl;
}
system("pause");
return 0;
}