首页 > 其他分享 >【后缀自动机】Codeforces Round #305 (Div. 1) E. Mike and Friends

【后缀自动机】Codeforces Round #305 (Div. 1) E. Mike and Friends

时间:2023-07-05 19:32:54浏览次数:52  
标签:Mike int res Codeforces 305 next fa tail include


对所有的串加特殊字符隔开,单串建立后缀自动机。然后将每个的fa边反向建树,对树dfs得到dfs序,对dfs序建立线段树。询问离线,每个询问拆成1-(l-1)和1-r。。。按端点排序,然后每次加入线段树,查询k对应的节点的子树和。。。


#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 800005
#define maxm 1000005
#define eps 1e-12
#define mod 1000003
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R
#pragma comment(linker, "/STACK:102400000,102400000")
#define pii pair<int, int> 
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
// head

const int alpha = 27;

struct node
{
	int len, k;
	node *next[alpha], *fa;
}*h[maxn], *tail, *last, *root, pool[maxm];

struct Edge
{
	int v;
	Edge *next;
}E[maxm], *H[maxn], *edges;

struct qu
{
	int w, t, id, flag;
	qu(int w = 0, int t = 0, int id = 0, int flag = 0) : w(w), t(t), id(id), flag(flag) {}
}q[maxm];

vector<int> vec[maxn];
int sum[maxn << 2];
int in[maxn];
int out[maxn];
int res[maxm];
string s[maxn];
int n, m, dfs_clock;

void addedges(int u, int v)
{
	edges->v = v;
	edges->next = H[u];
	H[u] = edges++;
}

node* newnode(int len, int k)
{
	tail->len = len;
	tail->k = k;
	tail->fa = 0;
	memset(tail->next, 0, sizeof tail->next);
	return tail++;
}

void add(int c, int k)
{
	node *p = last, *np = newnode(p->len+1, k);
	last = np;
	for(; p && !p->next[c]; p = p->fa) p->next[c] = np;
	if(!p) np->fa = root;
	else {
		node *q = p->next[c];
		if(p->len + 1 == q->len) np->fa = q;
		else {
			node *nq = newnode(0, 0);
			*nq = *q;
			nq->len = p->len + 1;
			q->fa = np->fa = nq;
			for(; p && p->next[c] == q; p = p->fa) p->next[c] = nq;
		}
	}
}

void init()
{
	dfs_clock = 0;
	edges = E;
	tail = pool;
	last = root = newnode(0, 0);
	memset(H, 0, sizeof H);
	memset(res, 0, sizeof res);
}

int cmp(qu a, qu b)
{
	return a.w < b.w;
}

void DFS(int u)
{
	in[u] = ++dfs_clock;
	for(Edge *e = H[u]; e; e = e->next) DFS(e->v);
	out[u] = dfs_clock;
}

void pushup(int o)
{
	sum[o] = sum[ls] + sum[rs];
}

void build(int o, int L, int R)
{
	sum[o] = 0;
	if(L == R) return;
	int mid = (L + R) >> 1;
	build(lson);
	build(rson);
}

int query(int o, int L, int R, int ql, int qr)
{
	if(ql <= L && qr >= R) return sum[o];
	int mid = (L + R) >> 1, ans = 0;
	if(ql <= mid) ans += query(lson, ql, qr);
	if(qr > mid) ans += query(rson, ql, qr);
	return ans;
}

void updata(int o, int L, int R, int v)
{
	if(L == R) {
		sum[o]++;
		return;
	}
	int mid = (L + R) >> 1;
	if(v <= mid) updata(lson, v);
	else updata(rson, v);
	pushup(o);
}

void work()
{
	for(int i = 0; i <= n; i++) vec[i].clear();
	for(int i = 1; i <= n; i++) {
		cin >> s[i];
		if(i != 1) add(26, 0);
		for(int j = 0; s[i][j]; j++) {
			add(s[i][j] - 'a', i);
			vec[last->k].push_back(last - root);
		}
	}
	for(int i = 1; i <= n; i++) {
		h[i] = root;
		for(int j = 0; s[i][j]; j++)
			h[i] = h[i]->next[s[i][j] - 'a'];
	}
	for(node *p = pool + 1; p < tail; p++) addedges(p->fa - root, p - root);
	DFS(0);
	int tot = tail - pool;
	int cnt = 0, l, r, kk;
	for(int i = 1; i <= m; i++) {
		scanf("%d%d%d", &l, &r, &kk);
		q[cnt++] = qu(l-1, h[kk] - root, i, -1);
		q[cnt++] = qu(r, h[kk] - root, i, 1);
	}
	sort(q, q+cnt, cmp);
	build(1, 1, dfs_clock);	
	int j = 0;
	while(q[j].w <= 0 && j < cnt) {
		res[q[j].id] += query(1, 1, dfs_clock, in[q[j].t], out[q[j].t]) * q[j].flag;
		j++;
	}
	for(int i = 1; i <= n; i++) {
		for(int l = 0; l < vec[i].size(); l++) updata(1, 1, dfs_clock, in[vec[i][l]]);	
		while(q[j].w <= i && j < cnt) {
			res[q[j].id] += query(1, 1, dfs_clock, in[q[j].t], out[q[j].t]) * q[j].flag;
			j++;	
		}
	}
	for(int i = 1; i <= m; i++) printf("%d\n", res[i]);
}

int main()
{
	while(scanf("%d%d", &n, &m)!=EOF) {
		init();
		work();
	}
	
	return 0;
}




标签:Mike,int,res,Codeforces,305,next,fa,tail,include
From: https://blog.51cto.com/u_8692734/6634292

相关文章

  • codeforces 540D - Bad Luck Island
    记忆化搜索...#include<iostream>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<cstdio>#include<algorithm>#include<cstring>#include<climits>#include......
  • Educational Codeforces Round 150 A~D
    c题好难。A.GamewithBoardProblem-A-Codeforces题意给定若干个数字1,Alice和Bob每回合合并两个相同的数字,Alice先手。如果谁最先不能合并数字,谁就胜利。思路通过推导可以看出\(n<5\)时先手必输,否则先手胜利的策略是取得只剩下两个数字可以合并。代码voidsolve(){......
  • Codeforces Round 879 (Div.2) B ~ D
    D题补了一天...B.MaximumStrengthProblem-B-Codeforces题意给定两串数字,在这两串数字之间找两串数字,要求每一数位之差的绝对值之和最大,求最大值为多少。思路对较少的那串数字添加前导零,使两串数字长度一样。要使所求值最大,就要尽可能使两数字串上相同数位的值分别为0......
  • Codeforces Round 864(Div.2) A~C
    vp过三题,c是交互题,想起了打华师大校赛时的不愉快经历了。A.LiHuaandMazeProblem-A-Codeforces题意给定一个n×m的矩阵,矩阵中有两个点(x1,y1),(x2,y2)。可以往矩阵中添加障碍物,使两个点之间不存在任何路径,求添加的障碍物数量最少为多少。思路可以把其中一个点的四周围......
  • codeforces 树上题目总结
    codeforces树上题目总结CF1559D2先猜一个结论——一定能通过加边让一个森林变成一棵树,归纳一下发现是对的,并且随便加合法的边都符合条件,所以暴力是\(\mathcalO(n^2)\)的。那么考虑如何降低复杂度。我并没有想到。我一直是在往快速找到两个不属于同一集合的点这个方向思考的......
  • Codeforces 293B Distinct Paths
    发现\(n,m\)的数据范围是假的,因为每一步一个颜色最多也就\(k\le10\)种颜色,所以当\(n+m-1>k\)时一定无解。接下来发现这个数据范围挺小的,考虑状压,设\(f_{x,y}\)为走到\((x,y)\)点所用的颜色的集合,其可以由\(f_{x-1,y},f_{x,y-1}\)推来。然后就可以......
  • Codeforces Round 878 (Div3)
    B.BinaryCafe\(1\leqn,k\leq10^9\)题解:思维考虑两种情况第一种:钱足够多,每种咖啡都可以买的情况下,答案为\(2^k\)第二种:钱不够多,因为任一面值的钱数都有唯一的二进制表达方式,所以答案为\(n+1\)所以我们不妨先判断一下\(2^k\)有没有超过\(10^9\),如果超过了说明钱......
  • CodeForces 1508D Swap Pass
    洛谷传送门CF传送门先忽略掉所有\(a_i=i\)的点。考虑我们钦定一个点\(s\),每次与\(a_s\)换直到\(a_s=s\)为止。不难发现这样相当于在置换环上删掉\(a_s\)这个点。这样可以解决\(s\)所在的环。问题是可能会形成很多个环。我们把其他点按照\(s\)极角排序,注意......
  • Codeforces 585D Lizard Era: Beginning
    很容易想到可以对于每个任务选不去的那一个人进行搜索,时间复杂度\(O(3^n)\),明显过不了。发现\(n\le25,\lceil\frac{n}{2}\rceil\le13\),且各个任务间不会互相影响,便可以用折半搜索分成\(2\)部分来搜最后来合并。考虑如何合并两部分,令前一部分得到的值分别为\(a,b,c\),后......
  • Codeforces Round 881 Div2 A-F1题解
    codeforcesround881div2题解马上要秋招了,自己本事全丢了,感觉如果这样的话今年就估计要饿死了。先打div3,7月份得开始收心了A.SashaandArrayColoring题意,可以分任意组,每组的贡献是max-min,问最大贡献显然是贪心,从大到小配对一下就行,不想放代码了’B.LongLong给出一......