困难的串——回溯法
Posted lfri
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了困难的串——回溯法相关的知识,希望对你有一定的参考价值。
题目
如果一个字符串包含两个相邻的重复字串,则称它是“容易的串”,其他串称为“困难的串”。输入正整数n和L,输出由前L个字符组成的、字典序第n的困难的串。例如,当L = 3时,前7个困难的串分别是A、AB、ABA、ABAC、ABACA、ABACAB、ABACABA。输入保证答案不超过80个字符。
解题思路
从左到右依次考虑每个位置上的字符。因此,关键在于如何判断当前字符串是否已经存在连续的重复字串。类似于八皇后,我们只需判断当前皇后和前面的皇后是否冲突,而不必判断以前的皇后之间是否冲突(因为以前的已经判断过了)。同样的道理,我们只需判断当前串的后缀,而非所有的字串。
代码实现
1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn = 80 + 10; 7 int n, L; 8 int cnt; 9 int S[maxn]; 10 11 bool dfs(int cur) 12 { 13 if (cnt++ == n) 14 { 15 for (int i = 0; i < cur; i++) 16 { 17 if (i % 64 == 0 && i) printf(" "); 18 else if (i % 4 == 0 && i) printf(" "); 19 printf("%c", ‘A‘ + S[i]); 20 } 21 printf(" %d ",cur); 22 return 1; 23 } 24 for (int i = 0; i < L; i++) 25 { 26 S[cur] = i; 27 int ok = 1; 28 for (int j = 1; j * 2 <= cur + 1; j++) //尝试长度为j * 2的后缀 29 { 30 int equal = 1; 31 for (int k = 0; k < j; k++) //检查后一半是否等于前一半 32 { 33 if (S[cur - k] != S[cur - j - k]) 34 { 35 equal = 0; 36 break; 37 } 38 } 39 if (equal) 40 { 41 ok = 0; 42 break; 43 } 44 } 45 if (ok) if (dfs(cur + 1)) return 1; 46 } 47 return 0; 48 } 49 50 int main() 51 { 52 while (scanf("%d%d",&n,&L) == 2 && n) 53 { 54 cnt = 0; 55 dfs(0); 56 } 57 return 0; 58 }
以上是关于困难的串——回溯法的主要内容,如果未能解决你的问题,请参考以下文章