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


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值