两个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(caa)=(1+2)! / 1!2! = 6/2 = 3,其他f值分别为f(cba)=6, f(b)=1, 故d(caba) = f(cba) + f(caa) + f(b) = 3 + 6 + 1 = 10
既然,比它小的个数是10,序号自然是11了。
给物体一个编号称为编码,同理也有解码,即根据序号构造出这个物体。这个过程和刚才的很接近:一次确定各个位置上的字母即可。