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

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