1496:Word Index
题目链接:http://bailian.openjudge.cn/practice/1496
总时间限制:
1000ms
内存限制:
65536kB
描述
Encoding schemes are often used in situations requiring encryption or information storage/transmission economy. Here, we develop a simple encoding scheme that encodes particular types of words with five or fewer (lower case) letters as integers.
Consider the English alphabet {a,b,c,...,z}. Using this alphabet, a set of valid words are to be formed that are in a strict lexicographic order. In this set of valid words, the successive letters of a word are in a strictly ascending order; that is, later letters in a valid word are always after previous letters with respect to their positions in the alphabet list {a,b,c,...,z}. For example,
abc aep gwz
are all valid three-letter words, whereas
aab are cat
are not.
For each valid word associate an integer which gives the position of the word in the alphabetized list of words. That is:
a -> 1 b -> 2 . . z -> 26 ab -> 27 ac -> 28 . . az -> 51 bc -> 52 . . vwxyz -> 83681
Your program is to read a series of input lines. Each input line will have a single word on it, that will be from one to five letters long. For each word read, if the word is invalid give the number 0. If the word read is valid, give the word's position index in the above alphabetical list.
输入
The input consists of a series of single words, one per line. The words are at least one letter long and no more that five letters. Only the lower case alphabetic {a,b,...,z} characters will be used as input. The first letter of a word will appear as the first character on an input line.
The input will be terminated by end-of-file.
输出
The output is a single integer, greater than or equal to zero (0) and less than or equal 83681. The first digit of an output value should be the first character on a line. There is one line of output for each input line.
样例输入
z a cat vwxyz
样例输出
26 1 0 83681
题目理解:
输出某个字符串str在字典中的位置,若不是字典中的字符则输出0。
单词中每个字母严格递增
解题思路:
方法一:我的思路就是把字符串全部map映射起来,从一位数、两位数、三位数这样枚举存到字典里,然后再去查字典。。
应该就是暴力?找不到就输出0,找到了就输出对应的。。于是就AC了。
看AC代码1
但是感觉比较正常或者说通用的解法应该是方法二
参考blog:https://blog.csdn.net/lyy289065406/article/details/6648492
就是组合数学的方法
方法二思路:①判断输入的str是否是升序序列
②计算出比str长度少的所有字符串个数
③计算长度等于str,但值比str 小的字符串个数
组合数用数组c[n][m]表示
考虑一位数、两位数 字符串的个数 ,根据下面的公式和推理,我们可以
得到规律:
或者直接可以直接这样想。。 长度为n的字符串要满足升序排列, 只需要在26个字母中选出n个字符就可以了 因为升序排列只有一种。直接就C[26][n] 了
长度为1的字符串个数为c[26][1]个
长度为2的字符串个数为c[26][2]个
长度为3的字符串个数为c[26][3]个
长度为4的字符串个数为c[26][4]个
所以我们可以计算出比str长度少的所有字符串个数,
AC代码1:
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
map<string,int> dic;
int main(){
int i=1;
char c='a';
for(;i<=26;i++){
string str="";
str+=c;
dic[str]=i;
c++;
}
//两位的情况
for(int j='a';j<='z';j++){
for(int k=j+1;k<='z' && j!=k;k++){
string str="";
str+=(char)j;
str+=(char)k;
dic[str]=i++;
}
}
//三位数的情况
for(int j='a';j<='z';j++){
for(int k=j+1;k<='z' && j!=k;k++){
for(int m=k+1;m<='z' && m!=k && m!=j ;m++){
string str="";
str+=(char)j;
str+=(char)k;
str+=(char)m;
dic[str]=i++;
}
}
}
//四位数
for(int j='a';j<='z';j++){
for(int k=j+1;k<='z' && j!=k;k++){
for(int m=k+1;m<='z' && m!=k && m!=j ;m++){
for(int n=m+1;n<='z' && n!=j && n!=k && n!=m ;n++){
string str="";
str+=(char)j;
str+=(char)k;
str+=(char)m;
str+=(char)n;
dic[str]=i++;
}
}
}
}
for(int j='a';j<='z';j++){
for(int k=j+1;k<='z' && j!=k;k++){
for(int m=k+1;m<='z' && m!=k && m!=j ;m++){
for(int n=m+1;n<='z' && n!=j && n!=m && n!=k ;n++){
for(int q=n+1;q<='z' && q!=j && q!=k && q!=m && q!=n;q++){
string str="";
str+=(char)j;
str+=(char)k;
str+=(char)m;
str+=(char)n;
str+=(char)q;
dic[str]=i++;
}
}
}
}
}
string ss;
while(cin>>ss){
map<string,int>::iterator it=dic.find(ss);
if(it!=dic.end()){
cout<<it->second<<endl;
}
else{
cout<<0<<endl;
}
}
return 0;
}
方法二 AC代码二:
//wordIndex的
#include <iostream>
#include <string.h>
using namespace std;
int C[50][50]; //组合数
void initTable(){
//c n m= c n-1 m-1 + c n-1 m
for(int i=0;i<=26;i++){
for(int j=0;j<=i;j++){
if(j==0 || i==j )
C[i][j]=1;
else
C[i][j]=C[i-1][j-1]+C[i-1][j];
}
}
C[0][0]=0;
}
int main(){
initTable();
char str[50];
while(cin>>str){
int sum=0;
int len=strlen(str);
//判断是否升序
bool flag=false;
for(int i=1;i<len;i++){
if(str[i]<str[i-1])
{
cout<<0<<endl;
flag=true;
break;
}
}
if(flag){
continue;
}
//计算长度小于len的字符串的个数
for(int i=1;i<len;i++)
sum+=C[26][i]; //长度为i的字符串的个数 就是C[26][i] 长度为n的字符串要满足升序排列只需要在26个字母中选出i个字符就可以
//计算长度等于len,但值比str小的字符串个数
for(int i=0;i<len;i++){
char c=(i==0)?'a':str[i-1]+1; //枚举到这里 就证明i位之前小于的所有字符串已经枚举完毕
while(c<str[i]){ //枚举到的这个字符小于当前位对应的字符 那么枚举所有的以这个字符开头的字符串 直到相等之后再枚举下一位
sum+=C['z'-c][len-1-i]; //从剩下的可以枚举的字符数 中 选出 n( len-1-i)个 一开始写反了
c++;
}
}
cout<<sum+1<<endl;
}
return 0;
}