dp[i][j] 代表 长度 为 i 的 首字母 为 j 的字符串有多少个。
转移就是不停的往现有字符串前边合法的增加字符串
i 代表长度 j 代表 首字母 k 代表可以从上一个的哪个转移过来
for(int i=0;i<26;i++)
dp[1][i]=1;
for(int i=2;i<27;i++)
{
for(int j=0;j<26;j++)
{
for(int k=25;k>j;k--)
dp[i][j]+=dp[i-1][k];
}
}
计算的时候,先统计长度小的
再统计长度相同的, 注意只统计合法的。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
#define MAX 500
#define INF 0x3f3f3f3f
#define MS(x) memset(x,0,sizeof(x))
#define ll long long
ll dp[100][100];// length i front j
bool check(char * s)
{
int len=strlen(s);
int cur=-1;
for(int i=0;i<len;i++)
if(s[i]<=cur)
return false;
else
cur=s[i];
return true;
}
int main()
{
for(int i=0;i<26;i++)
dp[1][i]=1;
for(int i=2;i<27;i++)
{
for(int j=0;j<26;j++)
{
for(int k=25;k>j;k--)
dp[i][j]+=dp[i-1][k];
}
}
char s[100];
while(scanf("%s",s)!=EOF)
{
int len=strlen(s);
if(!check(s))
{
cout<<"0"<<endl;
continue;
}
ll ans=0;
for(int i=1;i<len;i++)
for(int j=0;j<26;j++)
ans+=dp[i][j];
for(int i=0;i<len;i++)
{
for(int j=0;j<s[i]-'a';j++)
{
if(i!=0&&j<=s[i-1]-'a')
continue;
ans+=dp[len-i][j];
}
}
cout<<ans+1<<endl;
}
return 0;
}