《编程思维与实践》1039.字符组合

《编程思维与实践》1039.字符组合

题目

在这里插入图片描述
在这里插入图片描述

思路

先将字符串去重+排序(保证每个组合中的字符按字典序),然后枚举出所有组合的情形,最后再进行字典序排序即可.

其中字符串的去重排序可以利用ASCII码值或者strchr进行桶排序,关键在于如何枚举所有组合的情形.

每个位置有两种可能(选或不选),但至少要选一个,所以一共有 2 n − 1 2^{n}-1 2n1种(减去都不选的情况)可能性.

不妨将选记为1,不选记为0,那么这就刚好与二进制是对应的:

以abc的所有组合为例,

000表示abc都不选 , 001对应c , 010对应b , 011对应bc , 100对应a , 101对应ac , 110对应ab , 111对应abc.

代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int cmp(const void* a,const void* b)   //字典序排序
{
    
    
	char* m=(char*)a;
	char* n=(char*)b;
	return strcmp(m,n);
} 

int main()
{
    
    
	int T;
	scanf("%d",&T);
	for(int i=0;i<T;i++)
	{
    
    
		char s[17];  //长度不超过16
		scanf("%s",s);
		char differ[17]={
    
    '\0'};   //桶
        int count=0;
		for(int j=0;j<strlen(s);j++)
		{
    
    
			if(strchr(differ,s[j])==NULL)
            {
    
    
                differ[count++]=s[j];
            }
		}
        differ[count]='\0';
        qsort(differ,count,sizeof(char),cmp);
		
        int temp=(1<<count)-1;   //所有组合结果数
        char result[temp][17];   //所有组合情形
		int possible[count];   //二进制枚举  
        memset(possible,0,sizeof(possible));
		for(int j=0;j<temp;j++)   //每位依此加1
		{
    
    
			possible[0]++;
            for(int k=0;k<count-1;k++)
            {
    
    
                if(possible[k]==2)  //进位
                {
    
    
                    possible[k]=0;
                    possible[k+1]++;
                }
            }
			int t=0;
			for(int k=0;k<count;k++)  
			{
    
    
				if(possible[k])
				{
    
    
					result[j][t++]=differ[k];
				}
			}
			result[j][t]='\0';
		}
		
		qsort(result,temp,sizeof(result[0]),cmp); //排序
		printf("case #%d:\n",i);
		for(int j=0;j<temp;j++)
		{
    
    
			printf("%s\n",result[j]);
		}
	}
	return 0; 
}

猜你喜欢

转载自blog.csdn.net/boxueyuki/article/details/130402730