codeforces 547E Mike and Friends

codeforces 547E Mike and Friends

题意

题解

代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define per(i, a, b) for(int i=(b)-1; i>=(a); i--)
#define sz(a) (int)a.size()
#define de(a) cout << #a << " = " << a << endl
#define dd(a) cout << #a << " = " << a << " "
#define all(a) a.begin(), a.end()
#define endl "\n"
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
//---

const int N = 200005;

int n, q, tlen;
int len[N], plen[N];
string s[N];

namespace Doubling {
    static const int N = ::N << 1;
    int t[N], wa[N], wb[N], sa[N], h[N];
    inline void sort(int *x, int *y, int n, int m) {
        rep(i, 0, m) t[i] = 0;
        rep(i, 0, n) t[x[y[i]]]++;
        rep(i, 1, m) t[i] += t[i-1];
        per(i, 0, n) sa[--t[x[y[i]]]] = y[i];
    }
    inline bool cmp(int *x, int a, int b, int d) {
        return x[a] == x[b] && x[a+d] == x[b+d];
    }
    inline void da(int *s, int n, int m) {
        int *x = wa, *y = wb;
        rep(i, 0, n) x[i] = s[i], y[i] = i;
        sort(x, y, n, m);
        for(int j = 1, p = 1; p<n; m = p, j<<=1) {
            p = 0;rep(i, n-j, n) y[p++] = i;
            rep(i, 0, n) if(sa[i] >= j) y[p++] = sa[i] - j;
            sort(x, y, n, m);
            swap(x, y);
            p = 1;
            x[sa[0]] = 0;
            rep(i, 1, n) x[sa[i]] = cmp(y, sa[i], sa[i-1], j)?p-1:p++;
        }
    }
    inline void cal_h(int *s, int n, int *rk) {
        int j, k = 0;
        for(int i = 1; i<=n; ++i) rk[sa[i]] = i;
        for(int i = 0; i<n; h[rk[i++]] = k) {
            for(k && --k, j = sa[rk[i]-1];s[i+k]==s[j+k];++k);
        }
    }
}

struct Seg {
    static const int N = Doubling::N * 22 + 7;
    int cntn;
    int ls[N], rs[N], cnt[N], rt[N];
    inline void upd(int pre, int &now, int p, int l, int r) {
        now = ++cntn;
        ls[now] = ls[pre];
        rs[now] = rs[pre];
        cnt[now] = cnt[pre] + 1;
        if(l == r) return ;
        int mid = l + r >> 1;
        if(p <= mid) upd(ls[pre], ls[now], p, l, mid);
        else upd(rs[pre], rs[now], p, mid+1, r);
    }
    inline int qry(int tl, int tr, int L, int R, int l, int r) {
        if(L<=l&&r<=R) {
            return cnt[tr] - cnt[tl];
        }
        int mid = l+r>>1, ans=0;
        if(L<=mid) ans += qry(ls[tl], ls[tr], L, R, l, mid);
        if(R>=mid+1) ans += qry(rs[tl], rs[tr], L, R, mid+1, r);
        return ans;
    }
}seg;

struct DA {
    static const int N = ::N << 1;
    int p[22][N], rk[N], in[N], Log[N], n;
    inline void Build() {
        Doubling::da(in, n+1, 300);
        Doubling::cal_h(in, n, rk);
        Log[0] = -1;for(int i = 1; i<=n; ++i) Log[i] = Log[i-1] + (i==(i&(-i)));
        for(int i = 1; i<=n; ++i) p[0][i] = Doubling::h[i];
        for(int j = 1; 1<<j<=n; ++j) {
            int lim = n+1-(1<<j);
            for(int i = 1; i<=lim; ++i) p[j][i] = min(p[j-1][i], p[j-1][i+(1<<j>>1)]);
        }
        rep(i, 1, n+1) seg.upd(seg.rt[i-1], seg.rt[i], Doubling::sa[i], 0, n);
    }
    inline int lcp(int a, int b) {
        if(a==b) return n;
        if(a>b) swap(a, b);++a;
        int t=Log[b-a+1];
        return min(p[t][a], p[t][b-(1<<t)+1]);
    }
}da;

inline int calcl(int l, int r, int k, int len) {
    int res = r;
    while(l<=r) {
        int mid = l+r>>1;
        if(da.lcp(mid, k) >= len) {
            res = mid;
            r = mid - 1;
        } else {
            l = mid + 1;
        }
    }
    return res;
}
inline int calcr(int l, int r, int k, int len) {
    int res = l;
    while(l<=r) {
        int mid = l+r>>1;
        if(da.lcp(k, mid) >= len) {
            res = mid;
            l = mid + 1;
        } else {
            r = mid - 1;
        }
    }
    return res;
}

inline void solve() {
    int l, r, k;
    cin >> l >> r >> k;
    int rk = da.rk[plen[k-1]+1];
    int tl = calcl(1, rk, rk, len[k]);
    int tr = calcr(rk, da.n, rk, len[k]);
    int L = plen[l-1]+1;
    int R = plen[r]-1;
    cout << seg.qry(seg.rt[tl-1], seg.rt[tr], L, R, 0, da.n) << endl;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    cin >> n >> q;
    rep(i, 1, n+1) {
        cin >> s[i];
        len[i] = sz(s[i]);
        plen[i] = plen[i-1] + len[i] + 1;
        da.in[tlen++] = 27;
        rep(j, 0, sz(s[i])) da.in[tlen++] = s[i][j] - 'a' + 1;
    }
    da.in[tlen] = 0;
    da.n = tlen;
    da.Build();
    while(q--) {
        solve();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wuyuanyuan/p/9298788.html