uva 挂了,此题未AC,应该是对了
(uva挂了我还是头一回遇到)
AC了
题目大意:如果一个字符串包含两个相邻的重复子串,则称它是“容易的串”,
其他串称为“困难的串”。
输入正整数n和 l,
输出由前 l 个字符组成、字典序第n小的困难的串。
解题思路:在判断字符串中是否有重复的子串的时候,
只判断当前串的后缀,而非所有子串,回溯法
注意事项:输入0 0 停止
每4个字符输出一个空格(‘ ’)
每64个字符换一行
最后另起一行,并输出字符串长度
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,l,cnt;
int s[100];
bool huisu(int x) //返回true,表示已经得到解,不需要继续搜索
{
if(cnt++==n)
{
for(int i=0;i<x;++i)
{
if(i)
{
if(i%64==0)
cout<<endl;
else if(i%4==0)
cout<<' ';
}
printf("%c",'A'+s[i]); //输出方案
}
printf("\n%d\n",x);
return true;
}
for(int i=0;i<l;++i)
{
s[x]=i;
int ok=1;
for(int j=1;j*2<=x+1;++j) //尝试长度为j*2的后缀
{
int eq=1;
for(int k=0;k<j;++k) //检查后一半是否等于前一半
{
if(s[x-k]!=s[x-k-j])
{
eq=0;
break;
}
}
if(eq)
{
ok=0; //后一半等于前一半,不符合要求
break;
}
}
if(ok)
if(huisu(x+1)) //递归搜索,如果找到解,退出
return true;
}
return false;
}
int main()
{
while(cin>>n>>l&&n&&l)
{
cnt=0;
huisu(0);
}
return 0;
}