算法竞赛入门经典:第七章 暴力求解法 7.13困难的串

/*
困难的串:
如果一个字符串包含两个相邻的重复子串,则称它是“容易的串”,其他串成为“困难的串”。例如:BB,ABCDACABCAB,ABCDABCD都是容易的,而D、DC、ABDAB、CBABCBA
都是困难的。
输入正整数n和L,输出由前L个字符组成的、字典序第n个小的困难的串。例如,当L=3时,前7个困难的串分别为:A、AB、ABA、ABAC、ABACA、ABACAB、ABACABA。
输入保证答案不超过80个字符

输入:
7 3
30 3
输出:
ABACA BA
ABACA BCACB ABCAB ACABC ACBAC ABA

分析:
从左到右一次考虑每位置上的字符。关键:
如何判断当前字符串是否存在连续的重复子串。例如,如何判断ABACABA是否包含连续重复子串呢?
方法1:检查所有长度为偶数的子串,判断前一半=后一半
方法2:只需判断当前串的后缀
八皇后的教训:只判断当前皇后与之前的皇后是否冲突,而不判断之前的皇后是否互相冲突


思路:
1 大致用到了全排列,都是在原来基础上进行累加,但不知何时加B何时加C
2 非相邻重复子串怎么筛选条件(判断当前串的后缀的后半部分与前半部分是否连续且重复,不需要完整判断整个字符串)
*/

/*
关键:
1 if(cnt++ == n)//用cnt累计字典序第n个困难串
2 printf("%c",iArr[i] + 'A');//由于iArr[i]是整数,加上字符'A'之后,确保字符是从A开始的
3 return 0;//这里使用返回值,是为后面判断是否已经达到跳出条件做准备
4 for(int m = 0; m < L; m++)//L表示困难串的长度
5 for(int j = 1; 2*j <= pos+1; j++)//这里是对2*j长度的当前串的后缀进行判断
6 				for(int k = 0 ; k < j ; k++)//确保连续的能被判断到
				{
					if(iArr[pos-k] != iArr[pos-k-j])
					{
						isEqual = false;//不是重复相等的情况
						break;
					}
				}
7 			if(isDiff)//如果是困难的串,递归调用下一趟
			{
				if(!dfs(pos+1,n,L,iArr))//如果已经找到字典序第n小的困难串,输出
				{
					return 0;
				}
			}
*/


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

#define MAXSIZE 1024

int cnt;

int dfs(int pos,int n,int L,int* iArr)
{
	if(cnt++ == n)//用cnt累计字典序第n个困难串
	{
		for(int i = 0 ; i < pos ; i++)
		{
			printf("%c",iArr[i] + 'A');//由于iArr[i]是整数,加上字符'A'之后,确保字符是从A开始的
		}
		putchar('\n');
		return 0;//这里使用返回值,是为后面判断是否已经达到跳出条件做准备
	}
	else
	{
		for(int m = 0; m < L; m++)//L表示困难串的长度
		{
			iArr[pos] = m;
			bool isDiff = true;
			for(int j = 1; 2*j <= pos+1; j++)//这里是对2*j长度的当前串的后缀进行判断
			{
				bool isEqual = true;
				for(int k = 0 ; k < j ; k++)//确保连续的能被判断到
				{
					if(iArr[pos-k] != iArr[pos-k-j])
					{
						isEqual = false;//不是重复相等的情况
						break;
					}
				}
				if(isEqual)//如果相等,说明是重复的,说明是简单串,不符合要求
				{
					isDiff = false;
					break;
				}
			}
			if(isDiff)//如果是困难的串,递归调用下一趟
			{
				if(!dfs(pos+1,n,L,iArr))//如果已经找到字典序第n小的困难串,输出
				{
					return 0;
				}
			}
		}
	}
	return 1;//如果没有找到就输出
}

int main(int argc,char* argv[])
{
	int n,L;
	while(EOF != scanf("%d %d",&n,&L))
	{
		int iArr[MAXSIZE];
		cnt = 0;
		dfs(0,n,L,iArr);
	}
	system("pause");
	return 0;
}

你可能感兴趣的:(算法竞赛)