模板
康托展开和逆康托展开是一个全排列到一个自然数的双射。\(n\)个数有\(n!\)种全排列,康托展开表示的是当前的排列在所有全排列中,按照字典序排位的顺序。
康托展开可以用来构建哈希表,压缩空间。
计算方法:
\[cantor[x]=a[n]*(n-1)!+a[n-1]*(n-2)!+a[n-2]*(n-3)!+\cdots +a[1]*0!
\]
其中\(a[i]\)表示在从第一个元素到第\(i-1\)个元素的所有未出现的元素中,小于元素i的元素个数。
比如对于三个元素\(\{ 1,2,3\}\):
排列 | 康托展开 | 位次 |
---|---|---|
1 2 3 | \(0*2!+0*1!+0*0!=0\) | 1 |
1 3 2 | \(0*2!+1*1!+0*0!=1\) | 2 |
2 1 3 | \(1*2!+0*1!+0*0!=2\) | 3 |
2 3 1 | \(1*2!+1*1!+0*0!=3\) | 4 |
3 1 2 | \(2*2!+0*1!+0*0!=4\) | 5 |
3 2 1 | \(2*2!+1*1!+0*0!=5\) | 6 |
康托展开可以通过两重循环实现,时间复杂度\(O(n^2)\),也可以使用线段树等数据结构优化。 |
int cantor(char* a,int n){
int cnt,hash=0;
for(int i=0;i<n;i++){
cnt=0;
for(int j=i+1;j<n;j++){
if(a[j]<a[i]) cnt++;
}
hash+=cnt*fac[n-i-1];
}
return hash;
}