这道题总体来说不难,唯一一个玄机是如何判断这是hard string。事实上,只要前面的串都判断过,只要考虑你后来新加上去字母之后,形成的新字符串,一切判断都是围绕最后一个字母展开的。(印证了书上,避免无用判断)。
代码如下,写的长了些,但是力求清楚易懂。
</pre><pre name="code" class="cpp">#include<iostream>
#include<algorithm>
#include<math.h>
#include<vector>
#include<string.h>
#include<set>
#include<map>
using namespace std;
int N,L;
int length;
char save[1000010]={0};
bool judge()
{
int n=strlen(save)-1; //我是从1开始算的。这样方便后面的判断
if(n==0 || n==1) return true; //边界情况处理,长度为1时一定是可以的。
if(save[n]!=save[n-1] && n<=3) //长度小于等于3时只要判断最后两个是不是一样即可。
{
return true;
}
int count=n/2; //这里的判断方法是,分组判断,把一个字符串分成两串单字符,两串双字符,以此类推。(都有最后一个字母)
int i=1;
bool judgement=false;
for(i=1;i<=count;i++)
{
int base1=n-i*2+1;
int base2=base1+i;
for(base1,base2;base2<=n;base1++,base2++)
{
if(save[base1]!=save[base2]) // indicate that it is legal
{
judgement=true;
break;
}
}
if(judgement==false)
{
return false;
break;
}
if(i==count)
{
return true;
break;
}
judgement=false;
}
}
bool jc=false;
int ct=0;
void dfs(int length,int depth)
{
if(ct==N && judge()==true)
{
int i=1;
int fff=strlen(save)-1;
for(i=1;i<=fff;i++)
{
putchar(save[i]);
if(i%4==0 && i!=fff && (i%64)!=0)
{
cout<<" ";
}
if(i==64 && i!=fff)
{
cout<<endl;
}
}
cout<<endl;
cout<<fff<<endl;
jc=true;
ct--;
return ;
}
if((judge()==false) || depth>length || jc==true) return ;
ct++;
int i=1;
for(i=1;i<=L;i++)
{
save[depth]='A'-1+i;
save[depth+1]='\0';
dfs(length,depth+1);
save[depth]='\0';
}
}
int main()
{
while(cin>>N>>L &&N && L)
{
ct=0;
jc=false;
save[0]='0';
save[1]='\0';
dfs(N,1);
memset(save,0,sizeof(save));
}
return 0;
}