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. 解决js加减乘除精度问题

    // 加法 const accAdd = (arg1, arg2) => {     var r1, r2, m;     try {         r1 = arg1.toString(). ...

  2. linux命令之------Tar解压缩

    Tar解压缩 作用:将解压缩后缀名为tar的压缩包 -f<备份文件>或—file=<备份文件>指定备份文件 -v或-verbose显示指令执行过程 -x或-extract或-g ...

  3. gdb 调试core文件报错: in free () from /lib64/libc.so.6 找不到原因啊

    运行程序死掉  找不到原因啊..gdb 跟踪与堆栈信息 贴出来了 麻烦大佬们看一下,给个回复,不胜感激!! Core was generated by `./scene_s0037 10037'.Pr ...

  4. 关于集成通用mapper的Mybatis代码生成器产生的model类注解

    主要是@Table.@Id.@GeneratedValue.@Column 4个注解 这四个注解都来自javax.persistence包,是Java持久层规范,单纯的Mybatis并不认识这四个注解 ...

  5. CSS各类布局

    http://www.liquidapsive.com/ 1 静态布局(Static Layout)网页上的所有元素的尺寸一律使用px作为单位.特点:不管浏览器尺寸具体是多少,网页布局始终按照最初写代 ...

  6. 重新学习MySQL数据库12:从实践sql语句优化开始

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/a724888/article/details/79394168 本文不堆叠网上海量的sql优化技巧或 ...

  7. 范仁义html+css课程---4、文本标签

    范仁义html+css课程---4.文本标签 一.总结 一句话总结: 文本标签大致掌握一下,做到它站在你对面的时候最好认得,认不得也没关系,直接百度 1.ins标签.u标签和del标签 作用? ins ...

  8. semi-join子查询优化 -- FirstMatch策略

    FirstMatch执行semi-join子查询的一种策略. 类似于MySQL 5.x中如何执行in.exists子查询. 让我们以搜索拥有大城市的国家为例: select * from Countr ...

  9. Spark程序进行单元测试-使用scala

    Spark 中进行一些单元测试技巧:最近刚写了一点Spark上的单元测试,大概整理了一些 rdd测试 spark程序一般从集群中读取数据然后通过rdd进行转换,这其中涉及到集群,每次修改bug,上传到 ...

  10. java获取ubuntu某个目录下的所有文件信息

    java获取ubuntu某个目录下的所有文件信息 public List<VCFile> getAllFiles(String basicDirName) { List<VCFile ...