欢迎访问我的Uva题解目录哦 https://blog.csdn.net/richenyunqi/article/details/81149109
题目描述
题意解析
如果一个字符串包含两个相邻的重复子串,则称它是“容易的串”,其他串称为“困难的串”。例如,BB、ABCDACABCAB、ABCDABCD都是容易的串,而D、DC、ABDAB、CBABCBA都是困难的串。
输入正整数n和L,输出由前L个字符组成的、字典序第k小的困难的串。例如,当L=3时,前7个困难的串分别为A、AB、ABA、ABAC、ABACA、ABACAB、ABACABA。输入保证答案不超过80个字符。
算法设计
从左到右依次考虑每个位置上的字符。判断当前字符串是否已经存在连续的重复子串。判断方法是:在字符串中从后向前查找与最新加入的字符相同的字符,并查看以最新加入的字符和查找到的字符结尾的字符串是否相同,如果相同说明出现了重复的子串,那么就不符合要求,删去最新加入的字符,继续进行枚举,直到没有重复的子串。
C++代码
#include <bits/stdc++.h>
using namespace std;
int n, l;
bool f(string& s) {
//回溯
if (n == 0)//n为0时表示找到了结果,返回true
return true;
for (int i = 0; i < l; ++i) {
//枚举'A'到'A'+L字符
s += 'A' + i;
//从后向前查找与最新加入的字符相同的字符
for (int j = s.rfind('A' + i, s.size() - 2); j >= s.size() - 2 - j && j != string::npos; j = s.rfind('A' + i, j - 1))
if (s.substr(j + 1) == s.substr(j + j + 2 - s.size(), s.size() - 1 - j))//出现了重复的子串
goto loop;//删去最后的字符
--n;
if (f(s))//处理下个位置
return true;
loop:
s.pop_back();
}
return false;
}
int main() {
while (cin >> n >> l && n != 0) {
string s = "";
f(s);
for (int i = 0, group = 0; i < s.size(); ++i) {
//group表示组号
if (i != 0 && i % 4 == 0)
putchar((++group) % 16 == 0 ? '\n' : ' ');
putchar(s[i]);
}
printf("\n%d\n", s.size());
}
return 0;
}