题目描述:
字典序问题:在数据加密和数据压缩中需要对特殊的字符串进行编码。给定的字母表由 个小写字母组成。该字母表产生的升序字符串是指字符串中字母从左到右出现的次序与字母在字母表中出现的次序相同,且每个字符最多出现 次。对于任意长度不超过 的升序字符中,迅速计算出它在上述字典中的编码。
题意:
顾名思义,字典序,也就是要求给定字符串在升序字典中字典序的编号。
思路:
字典序编号如表:
1 | 2 | 3 | 4 | … | 26 | 27 | 28 | … |
---|---|---|---|---|---|---|---|---|
a | b | c | d | … | z | ab | ac | … |
计算字典序编号,可以转化为计算该字符串前面有多少个字符串。
- 计算长度小于 的升序字符串的总个数。
- 计算长度等于 的字典序小于(即编号在其前面)给定串的总个数。
递归求以 开头长度为 的升序字符串的总个数。
计算长度为 的升序字符串总个数。
参考代码:
:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL dfs(int i, int k) { //递归求以i开头长度为k的升序字符串的总个数
LL sum = 0;
if (k == 1) {
return 1;
}
for (int j = i + 1; j <= 26; j++) {
sum += dfs(j, k - 1);
}
return sum;
}
LL fun(int k) { //长度为k的升序字符串总个数
LL sum = 0;
for (int i = 1; i <= 26; i++) {
sum += dfs(i, k);
}
return sum;
}
signed solve() {
string s;
while (cin >> s) {
LL ans = 1;
int len = s.size();
//先把所有长度小于所求字符串长度的字符串的个数求出来
for (int i = 1; i < len; i++) {
ans += fun(i);
}
LL temp = 0;
for (int i = 0; i < len; i++) {
int num = s[i] - 'a' + 1; //下一位字符
int len2 = len - i; //获取当前的长度
for (int j = temp + 1; j < num; j++) {
ans += dfs(j, len2);
}
temp = num;
}
cout << ans << endl;
}
}
signed main() {
solve();
return 0;
}
def dfs(i, k):
sum = 0
if k == 1:
return 1
for j in range(i + 1, 27):
sum += dfs(j, k - 1)
return sum
def fun(k):
sum = 0
for i in range(1, 27):
sum += dfs(i, k)
return sum
def main():
s = input()
if False == s.isalpha():
print('请输入升序字母字符串')
else:
ans, l, temp = 1, len(s), 0
for i in range(1, l):
ans += fun(i)
for i in range(l):
num = ord(s[i]) - ord('a') + 1
len2 = l - i
for j in range(temp + 1, num):
ans += dfs(j, len2)
temp = num
print(ans)
if __name__ == "__main__":
main()