题目链接:
http://poj.org/problem?id=1850
题目大意:
给你一个字符串str,输出str在字典序全排列中的位置(从小到大排列)。
解题思路:
参考博文:http://www.cnblogs.com/lyy289065406/archive/2011/07/31/2122760.html
先判断str是不是升序序列,如果是升序序列,则为字典序的第1个,输出1。
不符合第一步的话,则分为两步计算str的字典序位置。
先计算比 str 的长度少的字符串总个数。
再计算长度和 str 一样,比 str 字典序的字符串的个数。
先来看第一步:
长度为 1 的字符串个数为 C(26,1)。
长度为 2 的字符串个数为 C(26,2)。
……
长度为 2 的字符串个数为 C(26,2)。
再来看第二步:
对于 str 的每一位 str[i] 和左边相邻的 str[i-1],如果str[i] > str[i-1],说明当前位置str[i]
至少
比前一位的 str[i-1] 大。
答案 ans 要加上用比 str[i]大的字母构成长度为 len-1-i 的字符串个数,即 C[26-ch][len-1-i]。
ch 从 str[i] 到 str[i-1] + 1。
AC代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; int C[27][27]; void ZuHe() { C[0][0] = C[1][0] = C[1][1] = 1; for(int i = 2; i <= 26; ++i) { C[i][0] = C[i][i] = 1; for(int j = 1; j < i; ++j) C[i][j] = C[i-1][j] + C[i-1][j-1]; } } char str[20]; int main() { ZuHe(); while(~scanf("%s",str)) { int ans = 0; int len = strlen(str); bool falg = true; for(int i = 1; i < len; ++i) { if(str[i] <= str[i-1]) { falg = false; break; } } if( !falg ) { printf("0\n"); continue; } int Time = len-1; while(Time) { ans += C[26][Time]; Time--; } int ch,ch1; for(int i = 0; i < len; ++i) { ch = str[i] - 'a'; if(i == 0) ch1 = 0; else ch1 = str[i-1] - 'a' + 1; while(ch > ch1) { ans += C[26-ch][len-1-i]; ch--; } } ans++; printf("%d\n",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-06 13:43:53