此题为排列组合题点击打开链接
题目大意:给出字符串判断它是第几个排列,排列按照先一位a-z, 然后排列两位的ab-yz,以此类推。。。。。本题最多五位,并且字母必须是升序
解题思路:就拿一个例子来举例吧d h k m,这是一个四位的字符
1.首先要计算所有的三位的全排列
2.再次计算四位的:a.首先计算首字母a b c 的全排列
b.再计算首字母为d 的排列,此时要根据后面的来计算,例如:应该计算字母 h 前面的三位的全排列,
然后在计算 h字母之后,但是 k字母之前的二位的全排列,最后计算字母 k 之后字母m 之前的一位的全排列,
最后答案是所有的和再加上本排列的1。
个人心得:本题菇凉我看了好久好久,还找大神解析,最终释然了。其中要注意边界部分,以及对数据的初始化,最重要的是要画图理解,
这样就很方便了。其中数据错了很多遍,原因就是多了一个等号,输出时少了+1,但就是这个错误导致自己看了半天,
这些错误都是致命错误,希望以后的自己能够认真一些!
代码如下:
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;//可以自己画图理解
int dp[30][6],sum[6];//dp记录以a-z为开头的长度分别为1-5的字符串个数,sum记录长度为1-5的字符串个数的和
void make_map()//构造数表
{
int i,j,k;
memset(sum,0,6);
memset(dp,0,180);
for(i=1;i<=26;i++)//长度为1时,不管以那个字母开头都是1
{
dp[i][1]=1;
}
sum[1]=26;//长度为1的字符串一共有26个
for(j=2;j<6;j++)
{
for(i=1;i<=26;i++)
{
for(k=i+1;k<=26;k++)
dp[i][j]+=dp[k][j-1];
sum[j]+=dp[i][j];
}
}
}
int is_ok(char *s)
{
int i,len=strlen(s);
if(len==1) return 1;
for(i=0;i<len-1;i++)
if(s[i]>=s[i+1])
return 0;
return 1;
}
int main()
{
char s[10];
int i,j,m,len,ans=0;
make_map();
while(scanf("%s",s)!=EOF)
{
ans=0;
m=is_ok(s);
if(m==0)
{
cout<<"0\n";
}
else
{
//
// for(i=1;i<=26;i++)
// {
// for(j=1;j<=5;j++)
// cout<<" "<<dp[i][j];
// cout<<endl;
// }
len=strlen(s);
for(i=1;i<len;i++)
ans+=sum[i];//cout<<"i:"<<sum[i]<<endl;
for(j=1;j<s[0]-'a'+1;j++)//将长度为len 的首字符之前的全排列找出来
ans+=dp[j][len];
for(i=1;i<len;i++)
{
for(j=s[i-1]-'a'+2;j<s[i]-'a'+1;j++)//容易出错的地方,此处是核心内容,目的是将两个字符之间的排列找出来
//例如:dhlk就是讲d-k之间的长度为3的排列找出来
{ //切记不能将k的长度为3的排列找出来,因为自身的排列只有一个,只找之前的
ans+=dp[j][len-i];
}
}
cout<<ans+1<<endl;//将自身加进去
}
}
return 0;
}