poj1850 code 字串的编号

题意:合法字串满足字符从左到右严格递增,所有的合法字串按照优先长度递增,其次字典序递增排列,求给定一个字符串,是否合法,若合法,编号为几?

分析:依旧是数位DP的思想,预处理出长度为i,首字母为j的字符串个数 f [ i ] [ j ]。

           给定字符串,首先加上长度小于它的字符串的个数。

                                   然后依次枚举第一个小于原字符串的位置,加上该位字母大于前一位、小于后一位的字符串的个数。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<queue>
#include<map>
#include<set>
using namespace std;
long long  f[20][30];//长度为i,以j开头的字符串的个数
int num[20],len;
int initi()
{
    int i,j,k;
    memset(f,0,sizeof(f));
    for(i=0;i<26;i++)
        f[1][i]=1;
    for(i=2;i<=10;i++)
    {
        for(j=0;j<26;j++)
        {
            for(k=j+1;k<26;k++)
                f[i][j]+=f[i-1][k];
        }
    }
}
long long cal()
{
    long long sum=0,i,j,k;
    for(i=1;i<len;i++)
    {
        for(j=0;j<26;j++)
            sum+=f[i][j];
    }
    for(i=0;i<len;i++)
    {
        if(i==0)
        {
            for(j=0;j<num[i];j++)
                sum+=f[len][j];
        }
        else
        {
            for(j=num[i-1]+1;j<num[i];j++)
                sum+=f[len-i][j];
        }
    }
    return sum;
}
int main()
{
    char s[20];
    int yes=1,i;
    initi();
    scanf("%s",s);
    len=strlen(s);
    num[0]=s[0]-'a';
    for(i=1;i<len;i++)
    {
        num[i]=s[i]-'a';
        if(num[i]<=num[i-1])
        {
            yes=0;
            printf("0\n");
            break;
        }
    }
    if(yes==1)
    {
        printf("%I64d\n",cal()+1);
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章