题意:已知给定字符串只会有小写字符出现,而且最多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; }