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 首先我显然可以随便构造出一棵树满足他所 ...
随机推荐
- mysql sum()函数 , 计算总和
mysql> select * from table1; +----------+------------+-----+---------------------+ | name_new | t ...
- python 得到列表的第二大的元素
code #coding=utf- l=[,,,,,,] max1=l[] max2=l[] if(max1>max2): pass else: max1,max2=max2,max1 :]: ...
- centos硬件查询
1.cpu个数: [root@localhost ~]# cat /proc/cpuinfo |grep "physical id"|sort|uniq|wc -lcpu核心数: ...
- 地址栏从url输入到页面显示
本文链接:https://blog.csdn.net/MiemieWan/article/details/85708052地址栏输入url, 要通过dns解析(浏览器是不能识别url地址的,需解析成i ...
- Hadoop综合大作业1
本次作业来源于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/3363 一.课程评分标准: 分数组成: 考勤 10 平时作业 30 爬 ...
- 公网IP地址就一定是A类地址和B类地址吗?那C类地址就一定是私有地址吗?
A,B,C三类中既有公网地址,也有私网地址:在A类地址中,10.0.0.0-10.255.255.255是私有地址.在B类地址中,172.16.0.0-172.31.255.255是私有地址.在C类地 ...
- mariadb 10.2/mysql 8.0实现递归
借助mysql 8.0的cte(它是iso sql标准的一部分),可以实现递归,mariadb 10.2.2开始支持递归cte,如下: +----+----------+--------------+ ...
- Xamarin图表开发基础教程(5)OxyPlot框架
Xamarin图表开发基础教程(5)OxyPlot框架 Xamarin.iOS中使用OxyPlot框架 在Xamarin.iOS平台上实现图表显示需要完成以下的步骤: 1.添加OxyPlot.Xama ...
- ROS tf-增加坐标系
博客参考:https://www.ncnynl.com/archives/201702/1312.html ROS与C++入门教程-tf-增加坐标系 说明: 介绍如何为TF增加额外固定的坐标系 为何增 ...
- [LeetCode] 191. Number of 1 Bits 二进制数1的个数
Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also know ...