字典序问题

来源:互联网 发布:阿里云输入法 编辑:程序博客网 时间:2024/05/29 14:26

问题描述

字典序问题。在数据加密和数据压缩中常需要对特殊的字符串进行编码。给定的字母表A由26个小写字母组成。该字母表产生的升序字符串中字母从左到右出现的次序与字母在字母表中出现的次序相同,且每个字符最多出现1次。例如,a,b,ab,bc,xyz等字符串都是升序字符串。现在对字母表中产生的所有长度不超过6的升序字符串,计算它在字典中的编码。

12...262728...ab...zabac...问题分析

假设字符串为“bdfk”,我们要求其位置,分3个方面进行考虑:

  1. 求出长度小于4的字符串个数
  2. 求出长度为4,开头字母小于b的字符串个数
  3. 求出长度为4,开头字母为b的字符串个数 
设函数g(ch,len),即g(ch,len)函数所求为ch为开头字母,len长度的字符串个数。f(len)函数,求长度小于字符串长度的个数,转化为g(ch,len)函数求解。

要注意的是f()函数和g()函数,循环的最后一个字符串开头字母为'z'-len+1;

#include<stdio.h>#include<string.h>int g(char ch,int len){int sum=0;char i;if(len==1)return 1;else{for(i=ch+1;i<='z'-len+1;i++)sum+=g(i,len-1);return sum;}}int f(int len){int sum=0;char i;for(i='a';i<='z'-len+1;i++)sum+=g(i,len);return sum;}int main(){char str[]="ab";int len=strlen(str);int count=0;char chb,ch;for(int i=1;i<len;i++)count+=f(i);  for(int i=0;i<len;i++){ if(i==0)chb='a';else{chb=str[i-1]+1;}for(ch=chb;ch<str[i]-1;ch++)count+=g(ch,len-i);} printf("%d\n",count+1);return 0;} 

解法2

#include<stdio.h>  #include<string.h>  int f(int m,int n)  {      int sum=1,sum1=1;             for(int i=1;i<=n;i++)          sum*=i;      for(int i=m;i>m-n;i--)          sum1*=i;      return sum1/sum;  }  int main()  {      int t;      int sum;      int len;      char s[10];      int a[10];      scanf("%d",&t);      while(t--)      {          getchar();          sum=1;          scanf("%s",s);          len=strlen(s);          for(int i=1;i<len;i++)          {              sum+=f(26,i);           //小于字符串长度的所有情况          }          for(int i=0;i<len;i++)          {                       a[i]=s[i]-96;           //计算每个字符从a开始的数值                      }                 int temp=1;          for(int i=len;i>0;i--)          {                                        for(int j=temp;j<a[len-i];j++)              {                  sum+=f(26-j,i-1);    //依次扫描字符              }              temp=a[len-i]+1;          }          printf("%d\n",sum);      }      return 0;      }