合法字符串
Time Limit:1000MS Memory Limit:65536K
4 6 a t c i s w
acis acit aciw acst acsw actw aist aisw aitw astw cist cisw citw istw
链接:http://acm.zjut.edu.cn/ShowProblem.aspx?ShowID=1437
/* ------------------------------------------------------------------------------------------- 大概想法:一般遇到这些题目,看似是排列组合的,有很多情况,而且每一步又和上一步可以组合的 自己一般都是往递归那边想。详见注释。 时间:15MS 内存:160K 时间复杂度分析:。。。。这个。。这个还真不会分析。。。。难道是O(nlogn)? ------------------------------------------------------------------------------------------- */ #include<stdio.h> #include<memory.h> //判断是否为元音字母 #define ISVOW(ch) ((ch == 'a') || (ch == 'e') || (ch == 'i') || (ch == 'o') || (ch == 'u')) //递归函数 void Print(int L, int nVowNeed,int nAssitNeed , int nIndex,int nStackTop) ; int nNum[28] ; //用来标志输入中有哪些字符,对应下标加上a,就是那个字符 char chStack[28] ; //栈,用来保存合法的字符串 int main(void) { int i = 0 ; int nVow = 0 ; //输入中元音字母的个数 int nAsist = 0 ; //输入中辅音字母的个数 int nVowNeed = 0 ; //合法字符串中元音最少需要的个数 int nAsistNeed = 0 ; //合法字符串中辅音最少需要的个数 int nStackTop = 0 ; //栈顶 int L = 0 ; int C = 0 ; int nTempTop = 0 ; int nTempL = 0 ; int nTempVowNeed = 0 ; int nTempAssitNeed = 0 ; char chTemp = 0 ; while(scanf("%d%d",&L,&C) != EOF) { getchar() ; memset(nNum,0,sizeof(nNum)) ; nVow = nAsist = 0 ; nVowNeed = 1 ; nAsistNeed = 2 ; nStackTop = 0 ; for(i = 0 ; i < C ; ++i) { scanf("%c",&chTemp) ; getchar() ; nNum[chTemp-'a'] = 1 ; if(ISVOW(chTemp)) { nVow++ ; } else { nAsist++ ; } } nTempTop = nStackTop ; nTempL = L ; nTempVowNeed = nVowNeed ; nTempAssitNeed = nAsistNeed ; for(i = 0 ; i < 21 ; ++i) //到21的原因是,u是排20 { chTemp = 'a' + i ; //每一次循环都要复位 nStackTop = 0 ; L = nTempL ; nVowNeed = nTempVowNeed ; nAsistNeed = nTempAssitNeed ; if(nNum[i] != 0 && nVow >=nVowNeed && nAsist >= nAsistNeed) { if(ISVOW(chTemp)) { chStack[nStackTop++] = chTemp ; L-- ; nVowNeed-- ; } else { chStack[nStackTop++] = chTemp ; L-- ; nAsistNeed-- ; } Print(L,nVowNeed,nAsistNeed,i+1,nStackTop) ; } } } return 0 ; } void Print(int L, int nVowNeed,int nAssitNeed , int nIndex,int nStackTop) { int i = 0 ; int nTempTop = nStackTop ; int nTempL = L ; int nTempVowNeed = nVowNeed ; int nTempAssitNeed = nAssitNeed ; char chTemp ; if(L <= 0 || nIndex >= 26) { if(L <= 0) //必须填满L才是合法的长度,不然的话会有短的输出 { chStack[nStackTop] = '\0' ; puts(chStack) ; } return ; } else { for(i = nIndex ; i < 26 ; ++i) //26是因为不是字符串中的第一个字符就可以 { nStackTop = nTempTop ; //每一次循环都要复位 L = nTempL ; nVowNeed = nTempVowNeed ; nAssitNeed = nTempAssitNeed ; chTemp = 'a' + i ; if(nNum[i] != 0) { if(ISVOW(chTemp) && nVowNeed > 0) //是元音且合法字符串中还木有一个无间字符 { chStack[nStackTop++] = chTemp ; nVowNeed-- ; L-- ; } else if(ISVOW(chTemp) && nVowNeed <= 0 && L > nAssitNeed) //是元音且合法字符串中已经有一个元音,且合法字符串中剩余的长度可以容纳需要的辅音字符个数 { chStack[nStackTop++] = chTemp ; nVowNeed-- ; L-- ; } else if(!ISVOW(chTemp) && nAssitNeed > 0 ) //元音同理 { chStack[nStackTop++] = chTemp ; nAssitNeed-- ; L-- ; } else if(!ISVOW(chTemp) && nAssitNeed <= 0 && L > nVowNeed) { chStack[nStackTop++] = chTemp ; nAssitNeed-- ; L-- ; } else continue ; Print(L,nVowNeed,nAssitNeed,i+1,nStackTop) ; } } } }