构造字符串 之 hdu 4850 Wow! Such String!
/*
话说之前读题都没读懂。。。
Each substring of A with length equal to or larger than 4 can appear in the string exactly once.
A的每个长度大于等于4的子串出现在传中恰好一次。(即:大于等于4的子串不能重复出现)
跟大神学的一种方法。。。
首先,长度为4的字符串有26^4种,故可猜测满足题意的最大长度的字符串的长度是26^4+3 (+3是因为鸽巢原理)。
此题关键就在于如何构造满足题意的字符串(废话啊。。。)
用数组used[][][][],来判断长度为4的字符串是否出现重复。
即:在每次增加一个字符(位置为pos),选择字母是时,判断used[str[pos-3]][str[pos-2]][str[pos-1]][str[pos]],是否为true,
若真,说明此子串之前有用过,无法选择该字母,
否则,可选。
复杂度:所能构造的最长字符串*26 <= (500000*26),可AC。。。
注意:
要先把 aaaa,bbbb,...,zzzz放到字符串中,否则它们无法被构造出来。
*/
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 const int MAX = 500005; 7 int N, len; 8 int str[MAX]; 9 bool used[26][26][26][26]; 10 11 12 int main() 13 { 14 //freopen("input.txt", "r", stdin); 15 //freopen("output.txt", "w", stdout); 16 memset(used, false, sizeof(used)); 17 len = 0; 18 19 for (int i = 0; i < 26; ++i) { 20 for (int j = 0; j < 4; ++j) { 21 str[len++] = i; 22 } 23 } 24 25 26 for (int i = 0; i < (len - 3); ++i) { 27 used[str[i]][str[i + 1]][str[i + 2]][str[i + 3]] = true; 28 } 29 30 bool Judge = true; 31 32 while (Judge) { 33 Judge = false; 34 for (int i = 0; i < 26; ++i) { 35 if (!used[str[len - 3]][str[len - 2]][str[len - 1]][i]) { 36 str[len] = i; 37 used[str[len - 3]][str[len - 2]][str[len - 1]][i] = true; 38 len++; 39 Judge = true; 40 } 41 } 42 } 43 44 while (~scanf("%d", &N)) { 45 if (N > len) { 46 printf("Impossible\n"); 47 } 48 else { 49 for (int k = 0; k < N; ++k) { 50 printf("%c", 'a' + str[k]); 51 } 52 printf("\n"); 53 } 54 } 55 return 0; 56 }