困难的串(Krypton Factor, UVa 129)回溯

版权声明:Nicolas https://blog.csdn.net/qq_42835910/article/details/86234777

如果一个字符串包含两个相邻的重复子串,则称它是“容易的串”,其他串称为“困难的串”。例如,BB、ABCDACABCAB、ABCDABCD都是容易的串,而D、DC、ABDAB、CBABCBA都是困难的串。输入正整数n和L,输出由前L个字符组成的、字典序第k小的困难的串。例如,当L=3时,前7个困难的串分别为A、AB、ABA、ABAC、ABACA、ABACAB、ABACABA。输入
保证答案不超过80个字符。
样例输入:
7 3
30 3

0 0
样例输出:
ABAC ABA

7

ABAC ABCA CBAB CABA CABC ACBA CABA

28

回溯递归,每次只需要考虑当前情况。每次只需要用新产生的字符串和前面的字符串对比即可(因为之前的已经比较过了),减少了对比量。

#include <iostream>
#include <string>
using namespace std; 
int n,m,cnt;
string s;
bool dfs(int cur){
	if(cnt++==n){//cnt记录第几次 ,一直递归n次结束 
		for(int i=0;i<cur;i++){
			if(i && i%(16*4)==0) cout<<endl;		 			
			else if(i && i%4==0)cout<<" ";
			cout<<s[i];	
		}
		cout<<endl<<cur<<endl;
		return true;
	}
	for(int i=0;i<m;i++){
		bool ok=true;
		s[cur]=char('A'+i);
		for(int j=1;2*j<=cur+1;j++){//每次比较j长的字符串。
			bool equal=true;
			for(int k=0;k<j;k++)
				if(s[cur-k]!=s[cur-k-j]){ equal=false; break;}
			if(equal){	ok=false; break; }
		}
		if(ok && dfs(cur+1)) return true;//如果找到解直接退出。
	}
	return false;
}


int main(int argc, char** argv) {
	while(cin>>n>>m && (n || m)){
		cnt=0;
		s.resize(n);
		dfs(0);
	}	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42835910/article/details/86234777