字典序问题。在数据加密和数据压缩中常需要对特殊的字符串进行编码。给定的字母表A由26个小写字母组成。该字母表产生的升序字符串中字母从左到右出现的次序与字母在字母表中出现的次序相同,且每个字符最多出现1次。例如,a,b,ab,bc,xyz等字符串都是升序字符串。现在对字母表中产生的所有长度不超过6的升序字符串,计算它在字典中的编码。
1
|
2
|
3
|
…
|
ab
|
ac
|
a
|
b
|
c
|
|
27
|
28
|
样例输入:
2
a
b
样例输出:
1
2
思路:比较麻烦的一道题,需要注意的是字符串是升序的,比如az下一个是bc而不是ba,,,,
拿dgh来说一下思路,
首先判断字符串长度为3,先算长度为1和2的所有情况,即从26个字母中选1个或两个字母,因为是升序,即
sum=C(26,1)+C(26,2);
之后再看字符串的第一个字符,为'd',之前有以a,b,c开头的长度为3的字符串,以a开头,后边2位需要在25个字母中选择(除了a),以b开头的后2位需要在24个字母中选择(除了a,b),以c开头的在23个字母(除了a,,b,c)中选择,,
即sum+=(C(25,2)+C(24,2)+C(23,2));
之后再看下一个字母'g',d与g之间有e,f,需要算以de开头以及以df开头的所有情况,即sum+=(C(21,1)+C(20,1)),
最后再加上h-'a'+1;
以这种思路代码:
#include<stdio.h>
#include<string.h>
int f(int m,int n)
{
int sum=1,sum1=1;
int i;
for(i=1;i<=n;i++)
sum*=i;
for(i=m;i>m-n;i--)
sum1*=i;
return sum1/sum;
}
int main()
{
int t;
int sum;
int i,j,len;
char s[10];
int a[10];
scanf("%d",&t);
while(t--)
{
getchar();
sum=1;
scanf("%s",s);
len=strlen(s);
for(i=1;i<len;i++)
{
sum+=f(26,i); //小于字符串长度的所有情况
}
for(i=0;i<len;i++)
{
a[i]=s[i]-96; //计算每个字符从a开始的数值
// printf("%d ",a[i]);
}
//printf("%d\n",f(26,2));
int temp=1;
for(i=len;i>0;i--)
{
for(j=temp;j<a[len-i];j++)
{
sum+=f(26-j,i-1); //依次扫描字符,计算所有情况
}
temp=a[len-i]+1;
}
printf("%d\n",sum);
}
return 0;
}