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;
    }

  • 相关阅读:
    Vue路由机制
    谷歌浏览器打不开应用商店的解决方法
    Vue报错——Component template should contain exactly one root element. If you are using vif on multiple elements, use velseif to chain them instead.
    Vue.js学习之——安装
    Vue使用axios无法读取data的解决办法
    关于localstorage存储JSON对象的问题
    2013年整体计划
    个人喜欢的警语收集
    Linux防火墙的关闭和开启
    Flex修改title 转载
  • 原文地址:https://www.cnblogs.com/taotao315/p/2950892.html
Copyright © 2011-2022 走看看