ACM水题-合法字符串 (AC,递归遍历,分情况,代码比较长)

合法字符串
Time Limit:1000MS  Memory Limit:65536K

Description:

一个合法的字符串是指最少含有一个元音字符和两个辅音字符的字符串。元音字符包括六个(a、o、e、i、u),其它小写字母都是辅音字符。现给你由多个小写字母组成的字符表,要你按字典序输出由这些字符表里的字母组成的所有长度为L的合法字符串。注:一个字符串里每个字母最多只能出现一次。

Input:

输入包含多组测试数据。每组测试数据的第一行包含两个整数L、C,分别表示合法字符串的长度和给定的字符表里的字母个数。3<=L<=15,L<=C<=26。

Output:

针对每组测试数据,按字典序输出所有长度为L的合法字符串。

Sample Input:

4 6
a t c i s w

Sample Output:

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


 

你可能感兴趣的:(c,测试,input,output)