例题7-5 UVA129 Krypton Factor(38行AC代码)

紫书刷题进行中,题解系列【GitHub|CSDN

例题7-5 UVA129 Krypton Factor(38行AC代码)

题目大意

用26个大写字母[A,Z]的前L个字母,构造无重复连续子串的字符串,按照字典序排序后,输出第n个字符串

思路分析

本题枚举可重复使用每个元素,若每次都是从小到大的顺序枚举字母,那么就是按字典序升序排列找到的结果,关键在于如何判断无重复连续子串?

如果按照输入样例绘制解答树,会发现,hard字符串是类似增量构造,每次只需从尾部向前判断是否存在重复连续子串即可

详细实现见代码注释

AC代码(C++11,相邻子串剪枝)

#include<bits/stdc++.h>
using namespace std;
int n, L;
vector<int> ans; // 存储答案
bool isHard(int val) { // 判断加入val后是否为Hard
    ans.push_back(val); // 先加入,最后发现不是hard在弹出
    for (int len=1; len <= ans.size()/2; len++) { // 遍历所有子串长度
        bool isSame=true;
        for (int j=0; j < len; j ++) { // 遍历相邻子串,判断是否相同
            if (ans[ans.size()-len+j] != ans[ans.size()-2*len+j]) {isSame=false; break;}
        }
        if (isSame) {ans.pop_back(); return false;} // 找到两个相同子串
    }
    return true;
}
void dfs(int& num) { // 递归搜索,num: 已找到hard的个数
    if (num == n) { // 输出
        for (int i=0; i < ans.size(); i ++) {
            printf("%c", ans[i]-1+'A');
            if ((i+1)%64 == 0 || i+1 == ans.size()) puts("");
            else if ((i+1)%4 == 0) putchar(' ');
        }
        printf("%d\n", ans.size());
        return; // 直接返回
    }
    for (int i=1; i <= L && num < n; i ++) { // 剪枝: num<n
        if (isHard(i)) {
            dfs(++num); ans.pop_back(); // 记得弹出无用的元素!!!
        }
    }
}
int main() {
    while (scanf("%d %d", &n, &L) == 2 && n && L) {
        ans.clear(); int num=0;
        dfs(num);
    }
    return 0;
}
发布了128 篇原创文章 · 获赞 87 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_40738840/article/details/104451375