Codeforces 1207 G. Indie Album
Codeforces 1207 G. Indie Album
解题思路
离线下来用SAM或者AC自动机就是一个单点加子树求和,套个树状数组就好了,因为这个题广义SAM不能存在 \(len[u] = len[fa]\) 的节点,需要特殊处理,所以写一个博客来贴板子,之前用Awd博客上的那个好像不太能处理干净。
code
/*program by mangoyang*/
#include <bits/stdc++.h>
#define inf ((ll) 1e18)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 1600005;
vector<int> g[N], d[N], rt;
vector<pair<int, int> > q[N];
string str[N];
char strr[N];
int ans[N], n, m;
namespace Bit{
int s[N];
inline void modify(int x, int y){
for(int i = x; i < N; i += i & -i) s[i] += y;
}
inline int query(int l, int r){
int res = 0;
for(int i = l - 1; i; i -= i & -i) res -= s[i];
for(int i = r; i; i -= i & -i) res += s[i];
return res;
}
}
namespace SAM{
vector<int> g[N];
int ch[N][26], dfn[N], len[N], fa[N], sz[N], size = 1, tail = 1, cnt;
inline int newnode(int x){ return len[++size] = x, size; }
inline void ins(int c, int pos){
int p = tail;
if(ch[p][c]){
if(ch[p][c] && len[ch[p][c]] == len[p] + 1){
int np = ch[p][c];
if(pos <= n) d[pos].push_back(np);
return (void) (tail = np);
}
int np = newnode(len[p] + 1), q = ch[p][c];
if(pos <= n) d[pos].push_back(np);
fa[np] = fa[q], fa[q] = np;
for(int i = 0; i < 26; i++) ch[np][i] = ch[q][i];
for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = np;
return (void) (tail = np);
}
int np = newnode(len[p] + 1);
if(pos <= n) d[pos].push_back(np);
for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
if(!p) return (void) (fa[np] = 1, tail = np);
int q = ch[p][c];
if(len[q] == len[p] + 1) fa[np] = q;
else{
int nq = newnode(len[p] + 1);
fa[nq] = fa[q], fa[q] = fa[np] = nq;
for(int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
} tail = np;
}
inline void addedge(){
for(int i = 2; i <= size; i++) g[fa[i]].push_back(i);
}
inline void dfs(int u){
dfn[u] = ++cnt, sz[u] = 1;
for(int i = 0; i < (int) g[u].size(); i++)
dfs(g[u][i]), sz[u] += sz[g[u][i]];
}
}
inline void build(int u){
int tmp = SAM::tail;
for(int i = 0; i < (int) str[u].size(); i++)
SAM::ins(str[u][i] - 'a', u);
for(int i = 0; i < (int) g[u].size(); i++)
build(g[u][i]);
SAM::tail = tmp;
}
inline void solve(int u){
for(int i = 0; i < (int) d[u].size(); i++)
Bit::modify(SAM::dfn[d[u][i]], 1);
for(int i = 0; i < (int) q[u].size(); i++){
int x = q[u][i].first, y = q[u][i].second;
ans[x] = Bit::query(SAM::dfn[y], SAM::dfn[y] + SAM::sz[y] - 1);
}
for(int i = 0; i < (int) g[u].size(); i++)
solve(g[u][i]);
for(int i = 0; i < (int) d[u].size(); i++)
Bit::modify(SAM::dfn[d[u][i]], -1);
}
int main(){
read(n);
for(int i = 1, x, y; i <= n; i++){
read(x);
if(x == 1)
cin >> str[i], rt.push_back(i);
else
read(y), cin >> str[i], g[y].push_back(i);
}
for(int i = 0; i < (int) rt.size(); i++)
build(rt[i]);
read(m);
for(int i = 1, x; i <= m; i++){
read(x), scanf("%s", strr);
int lenth = strlen(strr);
for(int j = 0; j < lenth; j++)
SAM::ins(strr[j] - 'a', n + 1);
q[x].push_back(make_pair(i, SAM::tail));
SAM::tail = 1;
}
SAM::addedge(), SAM::dfs(1);
for(int i = 0; i < (int) rt.size(); i++)
solve(rt[i]);
for(int i = 1; i <= m; i++) printf("%d\n", ans[i]);
return 0;
}
Codeforces 1207 G. Indie Album的更多相关文章
- CodeForces - 1207G :Indie Album(AC自动机 fail树上DFS)
题意:有N个串,给出的形式是拼接给出,对于第i行: (1,c)表示字符串i是单个字母c: (2,p,c)表示字符串i=在字符串p后面接上一个字母c. 然后给出M个提问,形式是(i,string).问 ...
- CF G. Indie Album AC自动机+fail树+线段树
这个套路挺有意思的. 把 $trie$ 和 $fail$ 树都建出来,然后一起跑一跑就好了~ #include <queue> #include <cstdio> #inclu ...
- CF G. Indie Album 广义后缀自动机+树链剖分+线段树合并
这里给出一个后缀自动机的做法. 假设每次询问 $t$ 在所有 $s$ 中的出现次数,那么这是非常简单的: 直接对 $s$ 构建后缀自动机,随便维护一下 $endpos$ 大小就可以. 然而,想求 $t ...
- [codeforces 549]G. Happy Line
[codeforces 549]G. Happy Line 试题描述 Do you like summer? Residents of Berland do. They especially love ...
- CodeForces 794 G.Replace All
CodeForces 794 G.Replace All 解题思路 首先如果字符串 \(A, B\) 没有匹配,那么二元组 \((S, T)\) 合法的一个必要条件是存在正整数对 \((x,y)\), ...
- codeforces 659 G. Fence Divercity 组合数学 dp
http://codeforces.com/problemset/problem/659/G 思路: f(i,0/1,0/1) 表示到了第i个,要被切的块开始了没有,结束了没有的状态的方案数 递推看代 ...
- Codeforces 803 G. Periodic RMQ Problem
题目链接:http://codeforces.com/problemset/problem/803/G 大致就是线段树动态开节点. 然后考虑到如果一个点还没有出现过,那么这个点显然未被修改,就将这个点 ...
- Codeforces 954 G. Castle Defense
http://codeforces.com/problemset/problem/954/G 二分答案 检验的时候,从前往后枚举,如果发现某个位置的防御力<二分的值,那么新加的位置肯定是越靠后越 ...
- Codeforces 746 G. New Roads
题目链接:http://codeforces.com/contest/746/problem/G mamaya,不知道YY了一个什么做法就这样过去了啊 2333 首先我显然可以随便构造出一棵树满足他所 ...
随机推荐
- vue-cli3 ios10白屏问题解决思路
在出现了这个问题之后先不要盲目的去瞎试,根据网上的方法试了个遍也没解决问题 先看报的是什么错,再针对的解决问题 首先出现的报错是 SyntaxError: Unexpected token '*' ...
- linux命令之------Chown命令
Chown命令 1) 作用:将指定文件的拥有者改为指定的用户或组. 2) -c:显示更改的部分的信息. 3)-f:忽略错误信息. 4)-h:修复符号链接. 5)-v:显示详细的处理信息. 6)-R:处 ...
- 最近在弄ionic3的时候遇到的一些问题(遇到就更新)
问题一(install提示errno -4048 和管理员权限) npm install npm ERR! code EPERM npm ERR! errno - npm ERR! syscall u ...
- GoCN每日新闻(2019-10-17)
GoCN每日新闻(2019-10-17) 通过go module管理go tool https://marcofranssen.nl/manage-go-tools-via-go-modules/ 使 ...
- hdu1501 Zipper[简单DP]
目录 题目地址 题干 代码和解释 参考 题目地址 hdu1501 题干 代码和解释 最优子结构分析:设这三个字符串分别为a.b.c,如果a.b可以组成c,那么c的最后一个字母必定来自a或者b的最后一个 ...
- AOP注解方式ApsectJ开发
AOP注解方式ApsectJ开发 引入配置文件 编写切面类配置 使用注解的AOP对象目标类进行增强 在配置文件中开启以注解形式进行AOP开发 在切面类上添加注解 注解AOP通知类型 @Before前置 ...
- 单细胞数据整合方法 | Comprehensive Integration of Single-Cell Data
操作代码:https://satijalab.org/seurat/ 依赖的算法 CCA CANONICAL CORRELATION ANALYSIS | R DATA ANALYSIS EXAMPL ...
- git 只提交部分修改文件
1.git status //查看修改文件状态 2.git add //将想要提交的文件add到本地库 4.git status //查看修改文件状态 3.git commit //提交add到 ...
- windows server2012 R2安装python3.x版本报错0x80240017
windows server2012 R2安装python3.x版本报错0x80240017 环境: windows server 2012 R2系统 问题: 安装python3.5版本时候出现错误0 ...
- postgrelsql 的 wm_concat : string_agg
string_agg,array_agg 这两个函数的功能大同小异,只不过合并数据的类型不同 array_agg(expression) 把表达式变成一个数组 一般配合 array_to_string ...