• [BZOJ2754][SCOI2012]喵星球上的点名


    [BZOJ2754][SCOI2012]喵星球上的点名

    试题描述

    a180285幸运地被选做了地球到喵星球的留学生。他发现喵星人在上课前的点名现象非常有趣。   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成。喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么这个喵星人就必须答到。 然而,由于喵星人的字码过于古怪,以至于不能用ASCII码来表示。为了方便描述,a180285决定用数串来表示喵星人的名字。
    现在你能帮助a180285统计每次点名的时候有多少喵星人答到,以及M次点名结束后每个喵星人答到多少次吗?  

    输入

    现在定义喵星球上的字符串给定方法:
    先给出一个正整数L,表示字符串的长度,接下来L个整数表示字符串的每个字符。
    输入的第一行是两个整数N和M。
    接下来有N行,每行包含第i 个喵星人的姓和名两个串。姓和名都是标准的喵星球上的字符串。
    接下来有M行,每行包含一个喵星球上的字符串,表示老师点名的串。

    输出

    对于每个老师点名的串输出有多少个喵星人应该答到。
    然后在最后一行输出每个喵星人被点到多少次。

    输入示例

    2 3
    6 8 25 0 24 14 8 6 18 0 10 20 24 0
    7 14 17 8 7 0 17 0 5 8 25 0 24 0
    4 8 25 0 24
    4 7 0 17 0
    4 17 0 8 25

    输出示例

    2
    1
    0
    1 2

    数据规模及约定

    对于30%的数据,保证: 
    1<=N,M<=1000,喵星人的名字总长不超过4000,点名串的总长不超过2000。
    对于100%的数据,保证:
    1<=N<=20000,1<=M<=50000,喵星人的名字总长和点名串的总长分别不超过100000,保证喵星人的字符串中作为字符存在的数不超过10000。

    题解

    求后缀数组,对于每一次点名,点到的对应了一个区间,对于第一问就是问区间中有多少个不同的数,用个主席树就好了;对于第二问不会做,暴力骗过。。。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 300010
    #define maxN 20010
    #define maxM 50010
    #define maxlog 19
    #define maxnode 6000010
    
    int n, m, Str[maxn], tag[maxn], lst[maxN], pre[maxn], st[maxM], Len[maxM], len;
    
    int rank[maxn], height[maxn], sa[maxn], Ws[maxn];
    bool cmp(int* a, int p1, int p2, int l) {
    	if(p1 + l > len && p2 + l > len) return a[p1] == a[p2];
    	if(p1 + l > len || p2 + l > len) return 0;
    	return a[p1] == a[p2] && a[p1+l] == a[p2+l];
    }
    void ssort() {
    	int *x = rank, *y = height;
    	int m = 0;
    	for(int i = 1; i <= len; i++) Ws[x[i] = Str[i]]++, m = max(x[i], m);
    	for(int i = 1; i <= m; i++) Ws[i] += Ws[i-1];
    	for(int i = len; i; i--) sa[Ws[x[i]]--] = i;
    	for(int j = 1, pos = 0; pos < len; j <<= 1, m = pos) {
    		pos = 0;
    		for(int i = len - j + 1; i <= len; i++) y[++pos] = i;
    		for(int i = 1; i <= len; i++) if(sa[i] > j) y[++pos] = sa[i] - j;
    		for(int i = 1; i <= m; i++) Ws[i] = 0;
    		for(int i = 1; i <= len; i++) Ws[x[i]]++;
    		for(int i = 1; i <= m; i++) Ws[i] += Ws[i-1];
    		for(int i = len; i; i--) sa[Ws[x[y[i]]]--] = y[i];
    		swap(x, y); pos = 1; x[sa[1]] = 1;
    		for(int i = 2; i <= len; i++) x[sa[i]] = cmp(y, sa[i], sa[i-1], j) ? pos : ++pos;
    	}
    	return ;
    }
    void calch() {
    	for(int i = 1; i <= len; i++) rank[sa[i]] = i;
    	for(int i = 1, j, k = 0; i <= len; height[rank[i++]] = k)
    		for(k ? k-- : 0, j = sa[rank[i]-1]; Str[i+k] == Str[j+k]; k++);
    	return ;
    }
    
    int Log[maxn], mnh[maxlog][maxn];
    void rmq_init() {
    	Log[1] = 0;
    	for(int i = 2; i <= len; i++) Log[i] = Log[i>>1] + 1;
    	for(int i = 1; i <= len; i++) mnh[0][i] = height[i];
    	for(int j = 1; (1 << j) <= len; j++)
    		for(int i = 1; i + (1 << j) - 1 <= len; i++)
    			mnh[j][i] = min(mnh[j-1][i], mnh[j-1][i+(1<<j-1)]);
    	return ;
    }
    int query(int l, int r) {
    	l++;
    	if(l > r) return len - sa[r] + 1;
    	int t = Log[r-l+1];
    	return min(mnh[t][l], mnh[t][r-(1<<t)+1]);
    }
    
    int ToT, rt[maxn], sumv[maxnode], lc[maxnode], rc[maxnode];
    void update(int& y, int x, int l, int r, int p) {
    	sumv[y = ++ToT] = sumv[x] + 1;
    	if(l == r) return ;
    	int mid = l + r >> 1; lc[y] = lc[x]; rc[y] = rc[x];
    	if(p <= mid) update(lc[y], lc[x], l, mid, p);
    	else update(rc[y], rc[x], mid + 1, r, p);
    	return ;
    }
    int que(int o, int l, int r, int up) {
    	if(r <= up) return sumv[o];
    	int mid = l + r >> 1, ans = que(lc[o], l, mid, up);
    	if(up > mid) ans += que(rc[o], mid + 1, r, up);
    	return ans;
    }
    int ask(int l, int r) {
    	return que(rt[r], 0, len, l - 1) - que(rt[l-1], 0, len, l - 1);
    }
    
    int vis[maxM], hhh[maxN];
    
    int main() {
    	n = read(); m = read();
    	for(int i = 1; i <= n; i++) {
    		int L = read();
    		while(L--) Str[++len] = read(), tag[len] = i;
    		Str[++len] = 10001;
    		L = read();
    		while(L--) Str[++len] = read(), tag[len] = i;
    		Str[++len] = 10001;
    	}
    	for(int i = 1; i <= m; i++) {
    		int L = read();
    		st[i] = len + 1; Len[i] = L;
    		while(L--) Str[++len] = read();
    		Str[++len] = 10001;
    	}
    	
    	ssort();
    	calch();
    	rmq_init();
    	/*for(int i = 1; i <= len; i++) printf("%d%c", Str[i], i < len ? ' ' : '
    ');
    	for(int i = 1; i <= len; i++) printf("%d%c", sa[i], i < len ? ' ' : '
    ');
    	for(int i = 1; i <= len; i++) printf("%d%c", tag[sa[i]], i < len ? ' ' : '
    ');
    	for(int i = 1; i <= len; i++) printf("%d%c", height[i], i < len ? ' ' : '
    '); // */
    	for(int i = 1; i <= len; i++) pre[i] = lst[tag[sa[i]]], lst[tag[sa[i]]] = i;
    	for(int i = 1; i <= len; i++) update(rt[i], rt[i-1], 0, len, pre[i]);
    	for(int i = 1; i <= m; i++) {
    		int now = rank[st[i]], l = 1, r = now, L, R;
    		while(l < r) {
    			int mid = l + r >> 1;
    			if(query(mid, now) < Len[i]) l = mid + 1; else r = mid;
    		}
    		L = l;
    		l = now; r = len + 1;
    		while(r - l > 1) {
    			int mid = l + r >> 1;
    			if(query(now, mid) < Len[i]) r = mid; else l = mid;
    		}
    		R = l;
    //		printf("%d [%d, %d]
    ", now, L, R);
    		printf("%d
    ", ask(L, R) - 1);
    		for(int j = L; j <= R; j++) if(tag[sa[j]] && vis[tag[sa[j]]] != i) vis[tag[sa[j]]] = i, hhh[tag[sa[j]]]++;
    	}
    	
    	for(int i = 1; i <= n; i++) printf("%d%c", hhh[i], i < n ? ' ' : '
    ');
    	
    	return 0;
    }
    

    真 TM 调死我了 = =

  • 相关阅读:
    linux jdk1.8安装
    spring boot jar包 linux 部署
    mysql linux安装
    codesmith 三层架构
    数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量
    android学习路线
    博客资源
    dotNET跨平台研究的相关文档
    Foundation框架—— 数组 (NSArray NSMutableArray )
    OC面向对象特性: 继承
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6643784.html
Copyright © 2020-2023  润新知