专栏文章
题解:P8203 [传智杯 #4 决赛] DDOSvoid 的馈赠
P8203题解参与者 2已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mind3c60
- 此快照首次捕获于
- 2025/12/02 00:26 3 个月前
- 此快照最后确认于
- 2025/12/02 00:26 3 个月前
前言
为了纪念我 csp2025 的 t3。
思路
首先我们可以发现 然后题目又求的是 的共同的被包含字串 的个数,那么我们可以往 bitset 上想,如果我们能维护出相对 合法的串并存入 bitset 中我们就可以做到 的复杂度,但是由于空间炸了所以考虑分块做我们对 分块,然后 bitset 的空间就降到了 的,然后我们就做完了,我们每 个分一组,插入 ACAM 中然后建出 fail 树求出每个点的合法点集之后我们遍历每一个 并求出其合法点集,查询时直接求并然后将个数加入答案即可。
代码
CPP#include <bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define rep1(i,x,y) for(register int i=x;i>=y;--i)
#define int long long
#define fire signed
#define il inline
template<class T> il void print(T x) {
if(x<0) printf("-"),x=-x;
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
template<class T> il void in(T &x) {
x = 0; char ch = getchar();
int f = 1;
while (ch < '0' || ch > '9') {if(ch=='-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
x *= f;
}
int T=1;
const int N=1e5+10,M=333;
bitset<M>f[N],g[N];
struct node{
int fl;
int s[30];
}tr[N];
vector<int>v[N];
int vis[N];
int idx=1;
vector<int>ve[N];
void modify(string s,int id) {
int p=1;
for(auto to:s) {
if(!tr[p].s[to-'a']) tr[p].s[to-'a']=++idx;
p=tr[p].s[to-'a'];
}
ve[p].pb(id);
}
void get() {
queue<int>q;
rep(i,0,25) tr[0].s[i]=1;
q.push(1);
while(q.size()) {
int x=q.front(),f=tr[x].fl;
q.pop();
rep(i,0,25) {
int &v=tr[x].s[i];
if(v) {
q.push(v);
tr[v].fl=tr[f].s[i];
}else v=tr[f].s[i];
}
}
}
int n,m,q;
string s[N],t[N];
int x[N],y[N],ans[N],bl[N],ll[N],rr[N];
void dfs(int x,int fa) {
for(auto to:ve[x]) f[x][to]=1;
for(auto to:v[x]) {
if(to==fa) continue;
f[to]|=f[x];
dfs(to,x);
}
}
void solve() {
in(n),in(m),in(q);
int len=sqrt(n);
rep(i,1,n) cin>>s[i],bl[i]=(i-1)/len+1;
rep(i,1,n) {
if(!ll[bl[i]]) ll[bl[i]]=i;
rr[bl[i]]=i;
}
rep(i,1,m) {
cin>>t[i];
}
rep(i,1,q) in(x[i]),in(y[i]);
vis[1]=-1;
rep(i,1,bl[n]) {
idx=1;
rep(j,ll[i],rr[i]) {
modify(s[j],j-ll[i]);
}
get();
rep(j,1,idx) v[tr[j].fl].pb(j);
dfs(1,0);
rep(j,1,m) {
int p=1;
g[j].reset();
for(auto to:t[j]) {
p=tr[p].s[to-'a'];
g[j]|=f[p];
}
}
rep(j,1,q) {
ans[j]+=(g[x[j]]&g[y[j]]).count();
}
rep(j,1,idx) f[j].reset(),v[j].clear(),ve[j].clear();
rep(j,1,idx) rep(x,0,25) tr[j].s[x]=tr[j].fl=0;
}
rep(i,1,q) printf("%lld\n",ans[i]);
}
fire main() {
while(T--) {
solve();
}
return false;
}
为啥我 csp 之前不会 ACAM 啊,/ll。
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...