算法课字典序问题

Posted osea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法课字典序问题相关的知识,希望对你有一定的参考价值。

题目描述

  在数据加密和数据压缩中常需要对特殊的字符串进行编码。给定的字母表A由26个小写字母组成。该字母表产生的升序字符串中字母从左到右出现的次序与字母在字母表中出现的次序相同,且每个字符最多出现1次。例如,a,b,ab,bc,xyz等字符串都是升序字符串。现在对字母表中产生的所有长度不超过6的升序字符串,计算它在字典中的编码。
 
 

… 

ab 

ac 

 

27 

28 

 

输入

第一行一个整数T,表示测试组数(1<=T<=1e6)。
接下来T行,每行一个长度不超过6的升序字符串(仅含小写字母)。 

 

输出

输出T行,每行一个整数代表答案。

 

样例输入

2
a
b

 

样例输出

1
2

 

 

【题意】

  其实这个题意是看这个列表看出来的,不重复的字母 按字典顺序给出,最大长度不超过6.

  和我们字典有点不同

  1、长度从小到大

  2、不存在重复的情况。

  

  多亏老师的提醒才能做出来,不然会在WA的路上越走越远。

  预处理所有f(i,j)  长度为i,以j字母开头的所有情况出来。

  

  预处理注意:1、不重复 ,2、长度占据一些位置,不能直接以下一个字母到z。

  

  求解答案时,注意如果当前是前一个字母的下一个位置不需要累加答案。

 

技术图片
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N = 30;
 6  
 7 int Sum_Len[N];
 8 int Pre_Len[N];
 9 int f[8][N];
10 char Str[N];
11 
12 // 预处理出所有f[i][j]
13 // f[i][j] 长度为i,j开头的所有情况
14 void Init()
15 
16     //长度为1时所有情况就是 1 
17     for(int i=0;i<27;i++)   f[1][i] = 1 ;
18  
19     //长度在递增时,转移方程为:f[len][i] += f[len-1][ i+1 ………z]
20     //注意一点的是,因为长度的限制,所以无法枚举到最后一个字符。
21     //f[len][i] += f[len-1][ i+1 ……… (‘z‘ - len - 1) ]
22     for( int Len = 2 ; Len <= 6 ; Len ++ )
23         for( int i=0 ; i < 26 ; i++ )
24             for( int j=i+1 ; j <= 26 - Len + 1 ; j++ )
25                 f[Len][i] += f[Len-1][j];
26             
27         
28     
29 
30     for(int i=1;i<=6;i++)
31         for(int j=0;j<26;j++)
32             Sum_Len[i] += f[i][j];
33         
34         //记录在统计长度为i时所有情况。
35         Pre_Len[i] = Pre_Len[i-1] + Sum_Len[i];
36     
37  
38 
39  
40 int main()
41 
42     Init();
43     int T;
44     scanf("%d",&T);
45     while(T--)
46         scanf("%s",Str+1);
47         int len = strlen( Str+1 ) ;
48         int Ans = Pre_Len[len-1] + 1 ;
49         
50         //预处理一个位置出来.
51         Str[0] = a - 1 ;
52         for( int i = 1 , Len = len ; i <= len ; i++ ,Len-- )
53             //如果是连着的情况就不统计,例如abc
54             
55             if( Str[i-1] + 1 == Str[i]  ) continue ;
56             
57             //如果不是连着的需要把对应的位置进行累加,注意累加的起点.
58             //如 ab(e) -> abc,abd 
59             for( int j = Str[i-1] - a + 1 ; j < Str[i]-a ; j++ )
60                 Ans += f[Len][j];
61             
62         
63         printf("%d\n",Ans);
64     
65     return 0 ;
66 
67  
68  
69  
70 /*
71  
72 a
73 1
74  
75 ab
76 27
77  
78 yz
79 351
80  
81 abc
82 352
83  
84 bcd
85 652
86  
87 */
View Code

 

以上是关于算法课字典序问题的主要内容,如果未能解决你的问题,请参考以下文章

算法设计之字典序

算法设计之字典序

算法设计之字典序

贪心算法(入门)字典序最小问题&最小覆盖问题

排列算法——字典序法

排列算法——字典序法