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的更多相关文章

  1. CodeForces - 1207G :Indie Album(AC自动机 fail树上DFS)

    题意:有N个串,给出的形式是拼接给出,对于第i行:  (1,c)表示字符串i是单个字母c: (2,p,c)表示字符串i=在字符串p后面接上一个字母c. 然后给出M个提问,形式是(i,string).问 ...

  2. CF G. Indie Album AC自动机+fail树+线段树

    这个套路挺有意思的. 把 $trie$ 和 $fail$ 树都建出来,然后一起跑一跑就好了~ #include <queue> #include <cstdio> #inclu ...

  3. CF G. Indie Album 广义后缀自动机+树链剖分+线段树合并

    这里给出一个后缀自动机的做法. 假设每次询问 $t$ 在所有 $s$ 中的出现次数,那么这是非常简单的: 直接对 $s$ 构建后缀自动机,随便维护一下 $endpos$ 大小就可以. 然而,想求 $t ...

  4. [codeforces 549]G. Happy Line

    [codeforces 549]G. Happy Line 试题描述 Do you like summer? Residents of Berland do. They especially love ...

  5. CodeForces 794 G.Replace All

    CodeForces 794 G.Replace All 解题思路 首先如果字符串 \(A, B\) 没有匹配,那么二元组 \((S, T)\) 合法的一个必要条件是存在正整数对 \((x,y)\), ...

  6. codeforces 659 G. Fence Divercity 组合数学 dp

    http://codeforces.com/problemset/problem/659/G 思路: f(i,0/1,0/1) 表示到了第i个,要被切的块开始了没有,结束了没有的状态的方案数 递推看代 ...

  7. Codeforces 803 G. Periodic RMQ Problem

    题目链接:http://codeforces.com/problemset/problem/803/G 大致就是线段树动态开节点. 然后考虑到如果一个点还没有出现过,那么这个点显然未被修改,就将这个点 ...

  8. Codeforces 954 G. Castle Defense

    http://codeforces.com/problemset/problem/954/G 二分答案 检验的时候,从前往后枚举,如果发现某个位置的防御力<二分的值,那么新加的位置肯定是越靠后越 ...

  9. Codeforces 746 G. New Roads

    题目链接:http://codeforces.com/contest/746/problem/G mamaya,不知道YY了一个什么做法就这样过去了啊 2333 首先我显然可以随便构造出一棵树满足他所 ...

随机推荐

  1. vue-cli3 ios10白屏问题解决思路

    在出现了这个问题之后先不要盲目的去瞎试,根据网上的方法试了个遍也没解决问题 先看报的是什么错,再针对的解决问题 首先出现的报错是 SyntaxError: Unexpected token '*'  ...

  2. linux命令之------Chown命令

    Chown命令 1) 作用:将指定文件的拥有者改为指定的用户或组. 2) -c:显示更改的部分的信息. 3)-f:忽略错误信息. 4)-h:修复符号链接. 5)-v:显示详细的处理信息. 6)-R:处 ...

  3. 最近在弄ionic3的时候遇到的一些问题(遇到就更新)

    问题一(install提示errno -4048 和管理员权限) npm install npm ERR! code EPERM npm ERR! errno - npm ERR! syscall u ...

  4. GoCN每日新闻(2019-10-17)

    GoCN每日新闻(2019-10-17) 通过go module管理go tool https://marcofranssen.nl/manage-go-tools-via-go-modules/ 使 ...

  5. hdu1501 Zipper[简单DP]

    目录 题目地址 题干 代码和解释 参考 题目地址 hdu1501 题干 代码和解释 最优子结构分析:设这三个字符串分别为a.b.c,如果a.b可以组成c,那么c的最后一个字母必定来自a或者b的最后一个 ...

  6. AOP注解方式ApsectJ开发

    AOP注解方式ApsectJ开发 引入配置文件 编写切面类配置 使用注解的AOP对象目标类进行增强 在配置文件中开启以注解形式进行AOP开发 在切面类上添加注解 注解AOP通知类型 @Before前置 ...

  7. 单细胞数据整合方法 | Comprehensive Integration of Single-Cell Data

    操作代码:https://satijalab.org/seurat/ 依赖的算法 CCA CANONICAL CORRELATION ANALYSIS | R DATA ANALYSIS EXAMPL ...

  8. git 只提交部分修改文件

    1.git status //查看修改文件状态 2.git add  //将想要提交的文件add到本地库 4.git status  //查看修改文件状态 3.git commit  //提交add到 ...

  9. windows server2012 R2安装python3.x版本报错0x80240017

    windows server2012 R2安装python3.x版本报错0x80240017 环境: windows server 2012 R2系统 问题: 安装python3.5版本时候出现错误0 ...

  10. postgrelsql 的 wm_concat : string_agg

    string_agg,array_agg 这两个函数的功能大同小异,只不过合并数据的类型不同 array_agg(expression) 把表达式变成一个数组 一般配合 array_to_string ...