欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【算法学习笔记】15.暴力求解法04 回溯法02 困难的串

程序员文章站 2022-03-31 16:12:33
...

发现好久没来更新了,开学之后各种杂事,好久都没学习算法了,还好最近马上要学习计导里有关算法的部分了。明天还要预习一下,今天先暂时把上次写完的困难的串(“好久之前的事”)更新一下,再在十一假期中强烈补充算法知识。

 

困难的串仍然是回溯法的部分,既然是回溯法那么就要DFS然后及时返回。

 

题目:如果一个字符串包含两个相邻的重复子串,则称它是”容易的串“,其他串成为”困难的串“。例如”ABCDABCD“是容易的串,而”ABDAB“是困难的串。
输入正整数n和L,输出由前L个字符组成的,字典序第n小的困难的串。
样例输入:7   3
                 30  3
样例输出:ABACABA
                 ABACABCACBABCABACABCACBACABA

 

当然处理重复字串的内容,就要进行枚举字串的长度和起始位置。既然是重复字串,总字串长度一定是偶数,但是这种想法并没有利用到之前的串来进行后续判断。 要用回溯来看。

 

bool is_diff(int cur)
{
	//判断后缀的话最长也就是和之前已经排完的长度一样  cur+1表示已经排完的数的长度 
	for(int j=1;j+j<=cur+1;j++)//循环确定所要判断的子串长度
	{
		//开始判断
		int equal = 1;
		//此处必须用equal变量来记录 
		for(int k=0;k<j;k++)	if(S[cur-k]!=S[cur-k-j]) //此处的判断k<j是个亮点 
		{	equal=0 ; break;}
		if(equal)
			return false;
	}
	return true;	
}

int dfs(int cur)
{
	if(cnt++==n)//说明已经找到了第n个困难的串,输出即可。 
	{
		//输出此串 
		for(int i=0;i<cur;i++)
			putchar('A'+S[i]);
		putchar('\n');
		return 0;//表示结束 
	}
	
	//开始对S[cur] 进行研究
	for(int i=0;i<L;i++) //尝试向S[cur] 填入0~L-1的数
	{
		S[cur]=i;
		//每次填入的时候就要进行判断是否和前面已经写好的串存在相邻且重复 为清晰判断过程单独写一个函数 
	 	if(is_diff(cur)) 
	 	{
	 		//这里要循环退出! 
	 		if(dfs(cur+1)==0)
	 			return 0;
	 	}
	}
	return 1;
}