变进制数

全排列哈希
我们熟知的数一般都是常进制数,所谓常进制数就是该数的每一位都是常数进制:

  • k进制数上的每一位都逢k进一, 第i位的位权是 k i k^i ki
    这里要介绍一种变进制数,用来表示字符串的排列状态
  • 这种数的第i位逢i进一,第i位的位权是 i ! i! i!
  • 用d[i]来表示一个变进制数第i位上的数字
  • 一个n位变进制数的值就为 ∑ i = 0 n − 1 d [ i ] × i ! \sum\limits^{n - 1}_{i=0}d[i]×i! i=0n1d[i]×i!
    这是一个最大的9位变进制数

876543210

它对应的十进制数为

8 × 8! + 7 × 7! + 6 × 6! + …… + 1 × 1! + 0 × 0! = 9! - 1 = 362879

我们可以找到一个9位变进制数,与一个9位无重复串的某种排列一一对应

用d[i]表示字符串中的第i位与其前面的字符组成的逆序对个数

字符串的一种排列对应的变进制数的值为 ∑ i = 0 n − 1 d [ i ] × i ! \sum\limits^{n−1}_{i=0}d[i]×i! i=0n1d[i]×i!
这是字符串123x46758的与d[i]d[i]的对应关系

i 0 1 2 3 4 5 6 7 8
s[i] 1 2 3 x 4 6 7 5 8
d[i] 0 0 0 0 1 1 1 3 1
它对应的变进制数的值为
1 × 4! + 1 × 5! + 1 × 6! + 3 × 7! + 1 × 8! = 56304
因此可以用以下函数求字符串的一种排列对应的哈希值

int permutation_hash(char s[], int n)       //求长度为n的字符串某种排列的哈希值
{
    int ans = 0;
    for(int i = 0; i < n; i ++)
    {
        int d = 0;
        for(int j = 0; j < i; j ++)
            if(s[j] > s[i])  d ++;          //求s[i]与其前面的字符组成的逆序对个数
        ans += d * fact[i];
    }
    return ans;
}

n不能太大,通常不超过12,否则会溢出
时间复杂度为O(n²)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值