题意:已知给定字符串只会有小写字符出现,而且最多5位。串中的字符必须从左到右严格递增。对应的数字规则为:a -> 1;b ->2 ... z -> 26;ab -> 27;ac -> 28 ... az -> 51;bc -> 52 ... vwxyz -> 83681。对给出的输入串,输入其对应的数字,如果不符合则输出0。
思路:考虑到一共只有83681个可行串,不算太大,便通过26个字母的全组合打表出所有的串,之后二分查找。
2245:相当于求含有6个元素的全组合
1496代码:
#include <stdio.h>
#include <string.h>
char s[83682][6],t[6],res[6];
int used[27];
int top=0;
void dfs(int d,int e,int f){
int i;
if(d == e){
res[d] = '\0';
strcpy(s[++top],res);//按顺序打入表中
return ;
}
for(i = f;i<26;i++)
if(!used[i]){
used[i] = 1;
res[d] = i+'a';
dfs(d+1,e,i+1);
used[i] = 0;
}
}
void create(){//求1~5在26个小写字母上的全组合
int i;
for(i = 1;i<=5;i++){
memset(used,0,sizeof(used));
dfs(0,i,0);
}
}
int test(char x[6]){//判断串x是否可行
int i;
for(i=1;x[i]!='\0';i++)
if(x[i] <= x[i-1])
return 0;
return 1;
}
int compare(char x[6],char y[6]){//比较两个串的先后,
int len = strlen(x)-strlen(y);
if(!len)//如果长度相同就比较字典序
return strcmp(y,x);
return len<0?1:-1;//细心注意谁大谁小
}
int find(char x[6]){//二分查找
int low,high,mid,temp;
low = 1;
high = top;
while(low <= high){
mid = (low+high)>>1;
temp = compare(s[mid],x);
if(!temp)
return mid;
else if(temp < 0)
high = mid-1;
else
low = mid+1;
}
}
int main(){
freopen("a.txt","r",stdin);
create();//打表
while(scanf("%s",t)!=EOF){
if(test(t))//如果输入串可行
printf("%d\n",find(t));
else
printf("0\n");
}
return 0;
}
2245:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
using namespace std;
#define clc(s,t) memset(s,t,sizeof(s))
#define INF 0x3fffffff
int s[15],len,res[10];
int n;
void dfs(int from){
int i;
if(len == 6){
for(i = 1;i<=6;i++)
printf("%d ",res[i]);
printf("\n");
return ;
}
for(i = from;i<=n;i++){
res[++len] = s[i];
dfs(i+1);
len--;
}
}
int main(){
while(scanf("%d",&n) && n){
int i;
len = 0;
for(i = 1;i<=n;i++)
scanf("%d",&s[i]);
dfs(1);
printf("\n");
}
return 0;
}
1496(1850最多10个字符,和1496题意完全相同)的另一种dp思路:
dp[i][j]表示以字符 i 开头,长度为j的字符串的个数。dp[26][i]表示长度为i的字符串的总个数。每次对输入的字符串进行统计即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
using namespace std;
#define clc(s,t) memset(s,t,sizeof(s))
#define INF 0x3fffffff
int dp[27][12];
char s[12];
void init(){
int i,j,k;
clc(dp,0);
for(i = 0;i<26;i++)
dp[i][1] = 1;
dp[26][1] = 26;
for(j = 2;j<=10;j++)
for(i = 0;i<26;i++){
for(k = i+1;k<26;k++)
dp[i][j] += dp[k][j-1];
dp[26][j] += dp[i][j];
}
}
int test(char* s){
for(int i = 1;s[i];i++)
if(s[i] <= s[i-1])
return 0;
return 1;
}
int main(){
init();
while(scanf("%s",s) != EOF){
int i,j,len,num=0;
if(test(s)){
len = (int)strlen(s);
for(i = 1;i<len;i++)
num += dp[26][i];
for(i = 0;i<s[0]-'a';i++)
num += dp[i][len];
for(i = 1;s[i];i++)
for(j = s[i-1]-'a'+1;j<s[i]-'a';j++)
num += dp[j][len-i];
printf("%d\n",num+1);
}else
printf("0\n");
}
return 0;
}