【HDU】4850 Wow! Such String! 提出猜想题

Wow! Such String!

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 112    Accepted Submission(s): 31
Special Judge


Problem Description
Recently, doge starts to get interested in a strange problem: whether there exists a string A following all the rules below:

1.The length of the string A is N .
2.The string A contains only lowercase English alphabet letters.
3.Each substring of A with length equal to or larger than 4 can appear in the string exactly once.

Doge cannot solve the problem, so he turns to his brother Yuege for help. However, Yuege is busy setting problems. Would you please help doge solve this problem?
 

Input
There are several test cases, please process till EOF.
For each test case, there will be one line containing one integer N (1 ≤ N ≤ 500000).
Sum of all N will not exceed 5000000.
 

Output
For each case, please output one line consisting a valid string if such a string exists, or “Impossible” (without quotes) otherwise. You can output any string if there are multiple valid ones.
 

Sample Input
   
   
   
   
5 3 11 10 6 17 8
 

Sample Output
   
   
   
   
pwned wow suchproblem manystring soeasy muchlinearalgebra abcdabch
 

Source
2014西安全国邀请赛

传送门:【HDU】4850 Wow! Such String!

题目大意:给你一个整数n,让你输出一个字符串。必须满足以下条件:
1.字符串的长度为n。
2.这个字符串只包含小写字母。
3.字符串中长度大于等于4的子串最多只能出现一次。
如果无解输出Impossible。

题目分析:
这题我们就是提出猜想过掉的。。
因为大于等于4的子串只能出现一次,所以想到串最长只会达到26*26*26*26+3 = 456979的长度。
一开始是想到了AC自动机,想在AC自动机上每走三个结点就回到根。。可是这根本做不到= =于是又诞生了另一种奇葩的方法——每增加一个字母时从a~z for一遍,看这个字母会不会和前三个字母构成的子串在之前的串中已经出现,如果未出现过,那么这个位置上就决定是这个字母了,然后下个位置直接从接下去的字母中选取;如果已经出现相同子串则枚举下个字母,如果一直到z还是不能添加一个字母到本位置但是这次a~z中已经有至少一个添加到之前的位置上时,重头再for,否则结束循环(因为已经枚举完所有的26个字母且都已经与前面三个字母构成的子串出现过了)。一开始我们设的aaa作为起始串,然后输出最后得到的串的长度达到了456954!无限接近,然后输出还没有添加到串中的字母一看,竟然除了a,所有四个相同字母如bbbb,cccc等都没有添加进去。。。然后就机智的将它们全部放到前面去,再次输出一看,最长串长度正好456979!问题解决。(至此我也明白了四个字母的子串只出现一次的主串长度最长能达到(26 ^ 4) + 3 )

PS:可以大胆的猜想,可以有x个不同字符的长度大于等于m(m <= x)的子串最多只能出现一次的主串的最长长度可以达到(x ^ m) + m - 1!证明留待后人。

代码如下:

#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std ;

#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define clear( a , x ) memset ( a , x , sizeof a )

typedef long long LL ;

const int MAXN = 26 ;
const int MAXS = 500005 ;

bool vis[MAXN][MAXN][MAXN][MAXN] ;
int s[MAXS] ;

int main () {
	int n , l = 0 , flag = 1 ;
	clear ( vis , 0 ) ;
	REP ( i , 0 , MAXN )
		s[l + 3] = s[l + 2] = s[l + 1] = s[l] = i , l += 4 ;
	REP ( i , 3 , l )
		vis[s[i]][s[i - 1]][s[i - 2]][s[i - 3]] = 1 ;
	while ( flag ) {
		flag = 0 ;
		REP ( i , 0 , MAXN )
			if ( !vis[i][s[l - 1]][s[l - 2]][s[l - 3]] ) {
				s[l] = i ;
				vis[s[l]][s[l - 1]][s[l - 2]][s[l - 3]] = 1 ;
				l ++ ;
				flag = 1 ;
			}
	}
	while ( ~scanf ( "%d" , &n ) ) {
		if( n > l )
			puts ( "Impossible" ) ;
		else {
			REP ( i , 0 , n )
				putchar ( s[i] + 97 ) ;
			putchar ( '\n' ) ;
		}
	}
	return 0 ;
}


你可能感兴趣的:(HDU)