zoukankan      html  css  js  c++  java
  • [luoguP2336] [SCOI2012]喵星球上的点名(后缀数组 + 暴力)

    传送门

    原本的想法是把所有的串不管是名字还是询问都连起来,记录一下询问串在sa数组中的位置

    对于每个询问可以在sa数组中二分出左右边界,第一问用莫队,第二问差分乱搞。

    结果发现我差分的思路想错了,先写了一个暴力,二分出左右边界之后直接从l枚举到r,想试试正确性,就交了一遍,结果过了。。。。

    因为是暴力,可以不用二分左右边界,直接向左向右枚举扩展就可以了,st表也不用了,但我懒得改了

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define N 2000001
    
    using namespace std;
    
    int n, m, cnt, mx, len;
    int M[N], x[N], y[N], s[N], sa[N], b[N], d[N][21], Rank[N], Log[N], height[N], id[N], pos[N], ans[N], num[N];
    
    inline int read()
    {
    	int x = 0, f = 1;
    	char ch = getchar();
    	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
    	return x * f;
    }
    
    inline void build_sa()
    {
    	int i, k, p;
    	for(i = 0; i < mx; i++) b[i] = 0;
    	for(i = 0; i < len; i++) b[x[i] = s[i]]++;
    	for(i = 1; i < mx; i++) b[i] += b[i - 1];
    	for(i = len - 1; i >= 0; i--) sa[--b[x[i]]] = i;
    	for(k = 1; k <= len; k <<= 1)
    	{
    		p = 0;
    		for(i = len - k; i < len; i++) y[p++] = i;
    		for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
    		for(i = 0; i < mx; i++) b[i] = 0;
    		for(i = 0; i < len; i++) b[x[y[i]]]++;
    		for(i = 1; i < mx; i++) b[i] += b[i - 1];
    		for(i = len - 1; i >= 0; i--) sa[--b[x[y[i]]]] = y[i];
    		swap(x, y);
    		p = 1, x[sa[0]] = 0;
    		for(i = 1; i < len; i++)
    			x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
    		if(p >= len) break;
    		mx = p;
    	}
    }
    
    inline void build_height()
    {
    	int i, j, k = 0;
    	for(i = 0; i < len; i++) Rank[sa[i]] = i;
    	for(i = 0; i < len; i++)
    	{
    		if(k) k--;
    		j = sa[Rank[i] - 1];
    		while(s[i + k] == s[j + k]) k++;
    		height[Rank[i]] = k;
    	}
    }
    
    inline void build_st()
    {
    	int i, j;
    	for(i = 1; i < len; i++)
    	{
    		Log[i] = log2(i);
    		d[i][0] = height[i];
    	}
    	Log[i] = log2(i);
    	for(j = 1; (1 << j) < len; j++)
    		for(i = 1; i + (1 << j) - 1 < len; i++)
    			d[i][j] = min(d[i][j - 1], d[i + (1 << j - 1)][j - 1]);
    }
    
    inline int query(int l, int r)
    {
    	int t = Log[r - l + 1];
    	return min(d[l][t], d[r - (1 << t) + 1][t]);
    }
    
    inline int search2(int p, int llen)
    {
    	int r = p, l = 1, mid;
    	while(l <= r)
    	{
    		mid = (l + r) >> 1;
    		if(query(mid, p) >= llen) r = mid - 1;
    		else l = mid + 1;
    	}
    	return r;
    }
    
    inline int search1(int p, int llen)
    {
    	p++;
    	int l = p, r = len - 1, mid;
    	while(l <= r)
    	{
    		mid = (l + r) >> 1;
    		if(query(p, mid) >= llen) l = mid + 1;
    		else r = mid - 1;
    	}
    	return l - 1;
    }
    
    inline void solve()
    {
    	int i, j, l, r;
    	for(i = 1; i <= m; i++)
    	{
    		r = j = search1(Rank[id[i]], M[i]);
    		l = j = search2(Rank[id[i]], M[i]);
    		for(j = l; j <= r; j++)
    			if(!num[pos[sa[j]]]++ && pos[sa[j]]) cnt++, ans[pos[sa[j]]]++;
    		printf("%d
    ", cnt);
    		cnt = 0;
    		for(j = l; j <= r; j++) num[pos[sa[j]]] = 0;
    	}
    	for(i = 1; i <= n; i++) printf("%d ", ans[i]);
    }
    
    int main()
    {
    	int i, j, t;
    	n = read();
    	m = read();
    	for(i = 1; i <= n; i++)
    		for(j = 1; j <= 2; j++)
    		{
    			t = read();
    			while(t--)
    			{
    				pos[len] = i;
    				s[len++] = read() + 100000;
    			}
    			s[len++] = mx++;
    		}
    	for(i = 1; i <= m; i++)
    	{
    		M[i] = read();
    		id[i] = len;
    		for(j = 1; j <= M[i]; j++) s[len++] = read() + 100000;
    		s[len++] = mx++;
    	}
    	mx = 120000;
    	build_sa();
    	build_height();
    	build_st();
    	solve();
    	return 0;
    }
    

      

  • 相关阅读:
    【HAOI2014】走出金字塔
    【HAOI2008】圆上的整点
    LOJ #116 有源汇点有上下界的最大流
    ZOJ [P2314] 无源汇点有上下界模版
    最小费用最大流模版
    最大流模版 dinic
    最大流模版 EK
    HDU [P1533]
    HDU [2255] 奔小康赚大钱
    POJ [P2289] Jamie's Contact Groups
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/8287997.html
Copyright © 2011-2022 走看看