zoukankan      html  css  js  c++  java
  • 12 字典序问题

    在数据加密和数据压缩中常需要对特殊的字符串进行编码.给定的字母表A由26个小写英文字母组成,即A={a,b...z}.该
    字母表产生的长序字符串是指定字符串中字母从左到右出现的次序与字母在字母表中出现的次序相同,且每个字符最
    多出现1次.例如,a,b,ab,bc,xyz,等字符串是升序字符串.

    思想:排列组合问题

    考察一般情况下长度不超过k的升序字符串

    设以第i个字符打头的长度k的升序字符串个数位f(i,k),长度k的升序字符串总个数为g(k),则

    g(k)=累加f(i,k),i从1到26

    f(i,1)=1                                                                                  g(1)=累加f(i,1),i从1到26

    f(i,2)=累加f(j,1)=26-i,j从i+1到26                                           g(2)=累加f(i,2)=累加(26-i),i从1到26

    一般情况,有:

    f(i,k)=累加f(j,k-1),j从i+1到26                                          

    g(k)=累加f(i,k)=累加i(累加j,f(j,k-1)),i从1到26,j从i+1到26

    举例:对于字符串cfkn,首先有g(3),g(2),g(1)                                         长度小于4的所有串的个数

                                           其次有f(2,4),f(1,4)                                             首位小于第一个字母的4长度串的个数

                                           再次f(4,3),f(5,3)                                               以d,e开头的长度为3的串的个数

                                           再其次f(7,2),f(8,2),f(9,2),f(10,2)                          以g,h,i,j开头的长度为2的串的个数

                                          最后f(5,1),f(4,1),f(3,1),f(2,1),f(1,1)                      以l,m,n开头的长度为1的串的个数

    把以上相加后还需要加1,求出本字符串的序

    上述思想分析转自http://hi.baidu.com/hk2305621/item/36778b5156849eded48bacc7(为了节省打字时间)

    代码实现如下:

    #include <stdio.h>
    #include <string.h>
    #define MAX 20

    //以第i个字符开头长度不超过k的升序字符串个数
    int f(int i, int k)
    {
    int j;
    int sum = 0;
    if (k == 1) {
    return 1;
    }
    else if (k > 1 && k <= 26) {
    for (j = i+1; j <= 26; j++) {
    sum += f(j, k-1);
    }
    return sum;
    }
    else {
    printf("error\n");
    return 0;
    }
    }

    //长度不超过k的升序字符串总个数
    int g(int k)
    {
    int i;
    int sum = 0;
    for (i = 1; i<= 26; i++) {
    sum += f(i, k);
    }
    return sum;
    }

    int sum(char *str)
    {
    int total = 0;
    int len = strlen(str);
    int i;
    for (i = 1; i < len; i++) {
    total += g(i);
    }
    int k;
    for (k = 1; k < len; k++) {
    char temp;
    if (k == 1) {
    temp = 1;
    }
    else {
    temp = str[k-2] - 'a' + 2;
    }
    for (i = temp; i < str[k - 1] - 'a' + 1; i++) {
    //此处为+2因为当输入串为ac时,只增加以b开始长度为1的串计数,i='c'-'a'+2,以b(2)开始,'c'-'a'+1-1结束
    total += f(i, len - k + 1);
    //开始错在少len-k少+1,这样,计算bf时len=2,k=1,计算以a开头的两位字符串时计算成了1位
    }
    }
    char temp ;
    if (k == 1) {
    temp = 1;
    }
    else {
    temp = str[k-2] - 'a' + 2;
    }
    for (i = temp; i <= str[k - 1] - 'a' + 1; i++) {
    total += f(i, 1);
    }
    return total;
    }

    int main()
    {
    char input[MAX];
    while(gets(input))
    {
    //int len = strlen(input);
    //printf("%d : %d\n", f(input[0] - 'a' + 1, len), g(len));
    printf("%d\n", sum(input));
    }
    return 0;
    }

  • 相关阅读:
    c# 利用反射设置属性值
    C#中扩展方法
    Python与Ruby比较
    Python 学习笔记(半ZZ半自己写)
    c# 写的一个类帮助器(动态生成类 动态类 动态属性)
    c#学习python
    LBS中从数据库查询某经纬度2KM范围内的数据 针对大数据量的性能优化
    隐藏ToString等系统自带方法
    C#命名规范
    SQL Server 数值四舍五入,小数点后保留2位
  • 原文地址:https://www.cnblogs.com/taotao315/p/2950892.html
Copyright © 2011-2022 走看看