描述:
两个a,一个b和一个c组成的所有串可以按照字典序编号为:
aabc(1),aacb(2),abac(3),···,cbaa(12)
任给一个字符串,能否方便地求出它的编码呢?例如,输入acab,则应输出5.
我们直接求解一般情况的问题(并不限定字母的种类和个数)。设输入串为S,记d(S)为S的各个排列中,字典序比S小的串的串的个数,则可以用递推法求解d(S),如图:
其中边上的字母表示“下一个字母”,f(x)表示多重集x的全排列个数。例如,根据第一个字母,可以把字典序小于caba的字符串分为3种:以a开头的,以b开头的,以c开头的,分别对应d(caba)的3棵子树。以a开头的所有串的字典序都小于caba,所以剩下的字符都可以任意排列,个数为f(cba);同理,以b开头的所有串的字典序也都小于caba,个数为f(caa);以c开头的串字典序不一定小于caba,关键要看后3个字符,因此这部分的个数为d(aba),还需要继续往下分。
至于f函数的求解,大部分组合数学书籍中均有介绍:设字符一共有k类,个数分别为n1,n2,···,nk,则这个多重集的全排列个数为
不难算出,,其他f值分别为f(cba)=6,f(b)=1,故d(caba)=f(cba)+f(caa)+f(b)=3+6+1=10。所以序号为11了。
“给物体一个编号”称为编码,同理也有“解码”,即根据序号构造出这个物体。这个过程和刚才的很接近:依次确定各个位置上的字母即可。例如,要求出序号为8(因此有7个比它小)的字符串,推理过程如下: