困难的串——回溯法

题目

如果一个字符串包含两个相邻的重复字串,则称它是“容易的串”,其他串称为“困难的串”。输入正整数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("\n");
18             else if (i % 4 == 0 && i)  printf(" ");    
19             printf("%c", 'A' + S[i]);
20         }
21         printf("\n%d\n",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 }

猜你喜欢

转载自www.cnblogs.com/lfri/p/9726776.html