其他分享
首页 > 其他分享> > [ SDOI 2016 ] 模式字符串

[ SDOI 2016 ] 模式字符串

作者:互联网

题目

Luogu
LOJ
Acwing

思路

001.png

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef unsigned long long ULL;
const int N = 1000010, P = 31;
int T, n, m, pre[N], suf[N];
char w[N], tmp[N];
ULL B[N] = { 1 }, prehash[N], sufhash[N];
int h[N], t[N << 1], p[N << 1], idx;
void add(int a, int b) { t[idx] = b, p[idx] = h[a], h[a] = idx++; }
int sz[N], vis[N], root;
void DFS_rt(int u, int fa, int tot) {
	sz[u] = 1;
	int mx = 0;
	for (int i = h[u], v; v = t[i], i != -1; i = p[i]) {
		if (vis[v] || v == fa) continue;
		DFS_rt(v, u, tot), sz[u] += sz[v], mx = max(mx, sz[v]);
	}
	mx = max(mx, tot - sz[u]);
	if (mx * 2 <= tot) root = u;
}
void DFS_sz(int u, int fa) {
	sz[u] = 1;
	for (int i = h[u], v; v = t[i], i != -1; i = p[i])
		if (!vis[v] && v != fa) DFS_sz(v, u), sz[u] += sz[v];
}
int sumpre[N], sumsuf[N], Tpre[N], Tsuf[N];
long long res;
int DFS(int u, int fa, int dep, int &mx, int mid, ULL hash) {
	int res = 0;
	mx = max(mx, dep);
	hash += w[u] * B[dep - 1];
	if (hash == prehash[dep]) {
		Tpre[dep % m]++;
		if (mid == pre[dep % m + 1]) 
			res += sumsuf[m - dep % m - 1];
	}
	if (hash == sufhash[dep]) {
		Tsuf[dep % m]++;
		if (mid == suf[dep % m + 1]) 
			res += sumpre[m - dep % m - 1];
	}
	for (int i = h[u], v; v = t[i], i != -1; i = p[i]) 
		if (!vis[v] && v != fa) res += DFS(v, u, dep + 1, mx, mid, hash);
	return res;
}
int Solve(int u, int tot) {	
	if (tot < m) return 0;
	DFS_rt(u, -1, tot), u = root;
	DFS_sz(u, -1), vis[u] = 1;
	int tag = 0, res = 0;
	if (w[u] == pre[1]) sumpre[0]++;
	if (w[u] == suf[1]) sumsuf[0]++;
	for (int i = h[u], v; v = t[i], i != -1; i = p[i]) {
		if (vis[v]) continue;
		int mx = 0;
		res += DFS(v, u, 1, mx, w[u], 0);
		tag = max(mx, tag);
		for (int i = 0; i <= mx; i++)
			sumpre[i] += Tpre[i], Tpre[i] = 0, 
			sumsuf[i] += Tsuf[i], Tsuf[i] = 0;
	}
	for (int i = 0; i <= tag; i++) sumpre[i] = sumsuf[i] = 0;
	for (int i = h[u], v; v = t[i], i != -1; i = p[i]) 
	 	if (!vis[v]) res += Solve(v, sz[v]);
	return res;
}
void Process(int s[], ULL hash[]) {
	for (int i = m + 1; i <= n; i++) s[i] = s[i - m];
	for (int i = 1; i <= n; i++)
		hash[i] = hash[i - 1] * P + s[i];
}
int main() {
	for (int i = 1; i <= 1e6; i++) B[i] = B[i - 1] * P;
	scanf("%d", &T);
	while (T--) {
		memset(vis, 0, sizeof vis), res = 0;
		memset(h, -1, sizeof h), idx = 0;
		scanf("%d%d%s", &n, &m, tmp + 1);
		for (int i = 1; i <= n; i++) w[i] = tmp[i] - 'A' + 1;
		for (int i = 1, a, b; i < n; i++)
			scanf("%d%d", &a, &b), add(a, b), add(b, a);
		scanf("%s", tmp + 1);
		for (int i = 1; i <= m; i++) pre[i] = tmp[i] - 'A' + 1;
		for (int i = 1; i <= m; i++) suf[i] = pre[m - i + 1];
		Process(pre, prehash), Process(suf, sufhash);
		cout << Solve(1, n) << endl;
	}
	return 0;
}	

标签:pre,2016,SDOI,int,long,LOJ,ULL,字符串,include
来源: https://www.cnblogs.com/Proteinlzl/p/15012552.html