1. 程式人生 > >困難的串(Krypton Factor, UVa 129)回溯

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

如果一個字串包含兩個相鄰的重複子串,則稱它是“容易的串”,其他串稱為“困難的串”。例如,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;
}