• 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 "
    "
    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;
    }
    
  • 相关阅读:
    Excel-单条件和多条件匹配搜索
    Excel-条件判断
    Excel-常用快捷键
    EXCEL-批量下拉填充
    Excel-数据分列的多种方法实现
    Excel-统一小括号格式(中文小括号,英文小括号)
    在WEB网页上模拟人的操作(批量操作)
    EXCEL-常用函数总结
    C语言学习——bsmap-2.74_main.cpp
    Linux --- awk
  • 原文地址:https://www.cnblogs.com/wuyuanyuan/p/9298788.html
Copyright © 2020-2023  润新知