码迷,mamicode.com
首页 > 其他好文 > 详细

【后缀自动机】 HDU 5431 AB String

时间:2015-09-20 11:53:20      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:

通道

题意:给出只有AB组成的字符串S,求第k个不在S中出现的串T。

思路:

代码:

技术分享
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <bitset>

#define LL long long
#define pii pair <int, int>
#define xx first
#define yy second
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;

const int N = 20010;

char s[N], res[20][35];
int n, nx[N * 35][2], rt, r[N * 35], tot, cnt, fa[N * 35], e[N * 35];
LL a[20];
LL f[35];

int newnode (int f) {
    nx[tot][0] = nx[tot][1] = -1;
    e[tot] = 0; fa[tot] = f;
    return tot++;
}

void init () {
    tot = 0;
    cnt = 0;
    rt = newnode (-1);
}

void ins (int x, int y) {
    int now = rt;
    for (int i = x; i <= x + y - 1; i++) {
        if (nx[now][s[i]] == -1) nx[now][s[i]] = newnode (now);
        now = nx[now][s[i]];
    }
    if (e[now] == 0) e[now] = 1, cnt++;
}

void getres (char *res, int k, int l) {
    int now = rt;
    for (int i = 0, j = l - 1; i < l; i++, j--) {
        LL cl = f[j], cr = f[j];
        if (now != -1) {
            if (nx[now][0] != -1) cl -= e[nx[now][0]];
            if (nx[now][1] != -1) cr -= e[nx[now][1]];
        }
        if (k <= cl) {
            if (now != -1) now = nx[now][0];
            res[i] = A;
        } else {
            k -= cl;
            if (now != -1) now = nx[now][1];
            res[i] = B;
        }
    }
    res[l] = 0;
}

void solve () {
    int vis[20], c = 0;
    memset (vis, 0, sizeof vis);
    int len = strlen (s);
    for (int i = 0; i < len; i++) s[i] -= A;
    for (int i = 1; i <= 33; i++) {
        init();
        if (len >= i) {
            for (int j = 0; i + j - 1 < len; j++) {
                ins (j, i);
            }
        }
        for (int j = tot - 1; j > 0; j--) e[fa[j]] += e[j];
        LL all = f[i] - cnt;
        for (int j = 1; j <= n; j++) if (!vis[j] && a[j] <= all) {
            c++;
            getres (res[j], a[j], i);
            vis[j] = 1;
        }
        if (c == n) break;
        for (int j = 1; j <= n; j++) a[j] -= all;
    }
    for (int i = 1; i <= n; i++) 
        printf ("%s\n", res[i]);
}

int main () {
    f[0] = 1;
    for (int i = 1; i <= 33; i++) f[i] = f[i - 1] * 2;
    int T; scanf("%d", &T);
    while (T--) {
        scanf ("%s", s);
           scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        solve ();
    }
}
View Code

 

【后缀自动机】 HDU 5431 AB String

标签:

原文地址:http://www.cnblogs.com/Rojo/p/4823034.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!