hdu 4850 Wow! Such String!(欧拉回路)
题目链接:hdu 4850 Wow! Such String!
题目大意:给定一个n,要求输出一个长度为n的字符串。而且不会有长度大于等于4的反复的子串。不能得到输出impossible。
解题思路:这题有一个误导性的地方,500000。事实上是构造不到那么长的,我们考虑全部不同样而且长度为4的串。一共同拥有s=264个,那么我们如果有一个非常长的串,满足不会有长度大于等于4的反复的子串,那么以0,1。2,3...的位置为起始。长度为4的子串一定都是s中的某一个串,由于不反复。所以肯定仅仅有264个位置做为起始点。加上最末尾的3个字符,一共是264+3的长度是能够构造条件串的。
构造方法事实上就是欧拉回路。以长度为3的串为节点。一共同拥有263个节点,每一个节点出度为26,入度为26,最后构造出的串起始就是走过边的权值,要求每一个节点刚好经过26次。我用的是贪心的方法,每次移动的下一个节点,一定是当前能移动到节点的中经过最少次数的节点。这样做去保证每一个节点都能刚好走26次。
注意:由于一開始是aaa的节点,所以对于每一个节点来说,权值为a的边要放在最后没路走的时候才去考虑,由于对于该图来说是一个欧拉回路,也就是说最后要回答aaa这个点,如果过程中就对权值a的边进行考虑。那么可能在过程中就将aaa的点走过一次,那么最后路就会被封死。所以一定要将回去的边留出来。
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 26*26*26;
const int mod = 26 * 26;
const int maxl = 500005;
int maxlen;
int v[maxn+5][30], c[maxn+5];
char s[maxl];
inline int get_next (int u, int k) {
return (u % mod) * 26 + k;
}
int find_next (int u) {
int x = 0, ans = -1;
for (int i = 1; i < 26; i++) {
if (v[u][i])
continue;
int tmp = get_next(u, i);
if (ans == -1 || c[tmp] < c[ans]) {
ans = tmp;
x = i;
}
}
return x;
}
void init () {
maxlen = maxn * 26 + 3;
int mv, u = 0;
memset(v, 0, sizeof(v));
for (mv = 0; mv < 3; mv++)
s[mv] = 'a';
while (true) {
int x = find_next(u);
int next = get_next(u, x);
if (c[next] == 26)
break;
c[next]++;
s[mv++] = x + 'a';
v[u][x] = 1;
u = next;
}
/*
for (int i = 0; i < maxn; i++) {
bool flag = false;;
for (int j = 0; j < 26; j++)
if (v[i][j] == 0)
flag = true;
if (flag)
printf("%d\n", i);
}
printf("%d %d\n", mv, maxlen);
*/
}
int main () {
int n;
init();
while (scanf("%d", &n) == 1) {
if (n <= maxlen) {
for (int i = 0; i < n; i++)
printf("%c", s[i]);
printf("\n");
} else
printf("Impossible\n");
}
return 0;
}
posted on 2019-04-03 21:42 xfgnongmin 阅读(190) 评论(0) 编辑 收藏 举报