Sicily 1866.Gene Reprogram 一种经典的hash方法

 http://202.116.77.69/sicily/show_problem.php?pid=1866

【题意】序列a 变成序列b 的最少步数 可执行的操作有

          1.  把交换字符串的前两个字符

          2. 把最前面的那个字符换到最后

【思路】  广搜  但是有几个地方要注意的  

         1.     每一位有4种可能 最多有12位 所以最多的状态数是4^12 但是ATGC 每一种的个数并不会改变而且 求的是组合而不是排列 所以状态空间的上限没有这么多 而是num=     N!/A!*C!*T!*G!

2.    可以用0 1 2 3 分别表示ACTG 即一个四进制位表示 一个状态就是一个四进制数值 因为最多是12位 所以这个数值最大就是4^12 判重的数组开 n

 

可以给每一个排列分配一个哈希值 这里的方法是

按字典序的大小给所有排列顶一个全序 给这个排列的哈希值就是它在这个全序里的序号

枚举当前排列的每一位 累加上当前为小于它而前面所有为都一样的排列个数
如 32120

枚举第一位时是
        0****
        1****
        2****
枚举第二位时是
         30***
         31***
第三位
        320**

。。。。
而计算某个带有重复元素的全排列的个数 的方法为 n!/ (n1!* n2!* n3!....)
n是序列的长度 ni 是第i中元素的总个数

 

   total是原串求得的 n!/ (n1!* n2!* n3!....)

int gethash(int a[])
{
    int sum=total;
    int ans=0;

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<a[i];j++)
            if(c[j])
                ans+=sum*c[j]/(n-i));    //即sum/  ((n-i)/c[j])  在草稿上演示一遍就知道了
        sum=sum*c[a[i]]/(n-i);
        c[a[i]]--;
    }
}

 

灰常好的哈希方法~  代码也很简练  

 

 

posted @ 2014-05-14 11:16  galaxy77  阅读(160)  评论(0编辑  收藏  举报