回溯法之避免无用判断 UVA129 Krypton Factor困难的串

题意:如果一个字符串包含两个相邻的重复子串,则称它是“容易的串”,其他串称为“困难的串”

输入正整数n和L,输出由前L个字符组成的并且它的字典序是第n小的串,和输出这个串的长度

样例输入:

7 3

30 3

样例输出:

ABAC ABA

7

ABAC ABCA CBAB CABA CABC ACBA CABA 

28

为了避免判断做无用功,每次都从尾部开始,枚举所有可能长度,在和前面的串匹配。因为前面的串已经匹配过,所以可以直接从尾部开始。

#include<iostream>
#include <string>
#include <string.h>
using namespace std;
const int maxn = 10000;
int cnt = 0,n,l; int c[maxn];
int dfs(int cur) {
	if (cnt++ == n) {//到达第n小的字典序
		int nextline = 0;
		for (int i = 0; i < cur; i++) {
			printf("%c", c[i] + 'A');
			if ((i + 1) % 4 == 0 && i != cur - 1) { 
				 nextline++;
				if (nextline % 16 == 0){printf("\n");continue;}
                                printf(" ");
			}
		}
		printf("\n%d\n",cur);
		return 0;
	}
	for (int i = 0; i < l; i++) {//搜索前l个字母
		int ok = 1;
		c[cur] = i;
		for (int j = 1; 2 * j <= cur + 1; j++) {//枚举长度,cur是从0开始所以要加一
			int equal = 1;
			for (int k = 0; k < j; k++) {//搜索长度为j的串是否和前面相邻的长度为j的串相等//不以cur结尾的串都在前面已经判断过,所以不用判断
				if (c[cur - k] != c[cur - k - j]) {//存在不等
					equal = 0; break;
				}
			}
			if (equal) {//若相等则不dfs下一个
				ok = 0; break;
			}
		}
		if (ok)if (!dfs(cur + 1))return 0;//如果搜索到了就退出
	}
	return 1;
}
int main()
{
#ifdef LOCAL
	freopen("data.in", "r", stdin);//scanf
	freopen("data.out", "w", stdout);//printf
#endif
	while (cin >> n >> l && n&&l) {
		cnt = 0;
		dfs(0);
	}
	//system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36973725/article/details/83929306