Cod sursa(job #2704064)

Utilizator ApostolIlieDanielApostol Daniel ApostolIlieDaniel Data 9 februarie 2021 18:35:14
Problema Radix Sort Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.46 kb
#include <bits/stdc++.h>

using namespace std;

using ll = long long;
#define pb push_back
#define dbg(x) cerr << #x << " " << x << "\n"


const int MAX_N = 2e5, MAX_K = 20;
int pos[MAX_N];
char str[MAX_N], s[MAX_K];
int order[MAX_N];

inline bool cmp (int a, int b) {
    return pos[a] < pos[b];
}

struct Faster {
    int a;
    int b;
    int idx;
    bool operator < (const Faster &other) const {
        if (a == other.a)
            return b < other.b;
        return a < other.a;
    }
};
Faster tags[MAX_N];
vector <Faster> freq[1 + MAX_N];
void radix_sort (int n) {
    int mx_tag = 0;
    for (int i = 0; i < n; i++) {
        mx_tag = max (mx_tag, tags[i].a);
        mx_tag = max (mx_tag, tags[i].b);
    }
    for (int i = 0; i <= mx_tag; i++)
        freq[i].clear ();
    for (int i = 0; i < n; i++)
        freq[tags[i].b].pb (tags[i]);
    int nr = 0;
    for (int i = 0; i <= mx_tag; i++)
        for (Faster f : freq[i])
            tags[nr++] = f;
    for (int i = 0; i <= mx_tag; i++)
        freq[i].clear ();
    for (int i = 0; i < n; i++)
        freq[tags[i].a].pb (tags[i]);
    nr = 0;
    for (int i = 0; i <= mx_tag; i++)
        for (Faster f : freq[i])
            tags[nr++] = f;
}

inline void get_order () {
    int n = strlen (str);
    for (int i = 0; i < n; i++)
        if (str[i] >= 'a' && str[i] <= 'z')
            pos[i] = 1 + str[i] - 'a' + 26;
        else
            pos[i] = 1 + str[i] - 'A';
    for (int depth = 0; (1 << depth) <= n; depth++) {
        int length = (1 << depth);
        for (int i = 0; i < n; i++) {
            int a = pos[i], b;
            if (i + length < n)
                b = pos[i + length];
            else
                b = 0;
            tags[i] = {a, b, i};
        }
        //sort (tags, tags + n);
        radix_sort (n);
        pos[tags[0].idx] = 1;
        for (int i = 1; i < n; i++)
            if (tags[i].a == tags[i - 1].a && tags[i].b == tags[i - 1].b)
                pos[tags[i].idx] = pos[tags[i - 1].idx];
            else
                pos[tags[i].idx] = 1 + pos[tags[i - 1].idx];
    }
    for (int i = 0; i < n; i++)
        order[i] = i;
    sort (order, order + n, cmp);
}
int k;
inline int compare (int start) {
    for (int i = 0; i < k; i++)
        if (str[i + start] != s[i])
            return (str[i + start] < s[i]) ? -1 : 1;
    return 0;
}
char part[64];
int main () {
    freopen ("seti.in", "r", stdin);
    freopen ("seti.out", "w", stdout);
    ios::sync_with_stdio (false);
    cin.tie (0); cout.tie (0);
    int n;
    cin >> n;
    int nr = 0;
    for (int i = 0; i < n; i++) {
        cin >> part;
        for (int j = 0; j < 64; j++)
            str[nr++] = part[j];
    }
    n *= 64;
    get_order ();
    int m;
    cin >> m;
    while (m--) {
        cin >> s;
        k = strlen (s);
        int lb = 0, rb = n - 1;
        int start = n;
        while (lb <= rb) {
            int mid = (lb + rb) / 2;
            if (compare (order[mid]) < 0)
                lb = mid + 1;
            else
                rb = mid - 1, start = mid;
        }
        lb = start, rb = n - 1;
        int finish = 0;
        while (lb <= rb) {
            int mid = (lb + rb) / 2;
            if (compare (order[mid]) > 0)
                rb = mid - 1;
            else
                lb = mid + 1, finish = mid;
        }
        cout << max (0, finish - start + 1) << "\n";
    }
    return 0;
}