题目:
字典序问题,给定一个长度不超过6的小写字母升序字符串(字符串中的字符相对顺序和字母表中的顺序一致),迅速计算出在字典中的编码,字典如:
1 2 3 ... 26 27 28 ...
a b c ... z ab ac ...
1 2 3 ... 26 27 28 ...
a b c ... z ab ac ...
思路:
总体思路为先计算出给定字符串前所有的个数,然后再加一
代码&详细注释思路:
#include <iostream>
#include <cstdlib>
//计算从i开始的长度为k的所有数的个数
//例如以a开头长度为2的所有组合个数
int CharacterCount(int i, int k)
{
int sum = 0;
if (k == 1) {
sum = 1;
} else {
//以i开头的长度为k的字符串的个数等于CharacterCount(m,k - 1)的和 //m是一个i+1到26的闭区间
for (int j = i + 1; j <= 26; ++j) {
sum += CharacterCount(j, k - 1);
}
}
return sum;
}
//计算长度为k的字符串的所有组合的总和个数
//例如以a开头,长度为2的所有组合的总和个数等于长度为2的加上长度为1的
int CharacterSumCount(int k)
{
int sum = 0;
//总和等于所有长度小于k的字符串组合之和
for (int i = 1; i <= 26; ++i) {
sum += CharacterCount(i, k);
}
return sum;
}
//总体思路为先计算出给定字符串前所有的个数再加一
int FindCode(std::string &str)
{
int code = 0; //保存最终结果
auto len = str.size();
//计算1~len-1的所有总和
for (int i = 1; i < len; ++i) {
code += CharacterSumCount(i);
}
//小于第一个字母的长度为k的所有组合
for (int i = 1; i < str[0] - 96; ++i) {
code += CharacterCount(i, len);
}
//以第一个字母作为开始字符的字符串组合总个数
for (int i = 1; i < str.size(); ++i) {
for (int j = str[i - 1] - 96 + 1; j < str[i] - 96; ++j) {
code += CharacterCount(j, str.size() - i);
}
}
return code + 1; //前面代码求出了给定字符串前所有的个数,加1就是给定字符串的编码
}
int main(int argc, char *argv[])
{
std::string str;
std::cin >> str;
if (str.size() > 6) {
std::cerr << "输入的字符串超过长度限制" << std::endl;
return EXIT_FAILURE;
}
std::cout << FindCode(str) << std::endl;
return EXIT_SUCCESS;
}