BZOJ3277——串
来源:互联网 发布:淘宝店页面背景图 编辑:程序博客网 时间:2024/05/30 04:47
0、题意:给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身)。
1、分析:这个题我问了吴大爷做法
首先建立后缀自动机,然后利用离线搞出每一个节点在多少个串中,这个用树状数组统计一下就好,和BZOJ2780一样,然后如果这个节点在不少于x个串中,我们把这个点的value赋值成这个节点父亲边的字符个数,否则为0。随后我们预处理一下从根到每个节点路径上的权值和。于是每个字符串的答案等于所有这个字符串的后缀节点的从根到该节点的权值和。
然后这个题就解决了
#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>using namespace std;#define M 200010#define LL long longinline int read(){ char ch = getchar(); int x = 0, f = 1; while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while('0' <= ch && ch <= '9'){ x = x * 10 + ch - '0'; ch = getchar(); } return x * f;}struct node{ int tranc[27], fa, len;} a[202010];int cnt, tail;char s[202010];int p, nq, q, np;int in[M], out[M], seg[M], num;int C[M], v[M];int lastins[M];int sum[M];struct gragh{ int head[M], to[M], Next[M], tot; inline void init(){ memset(head, -1, sizeof(head)); tot = 0; } inline void add(int u, int v){ ++ tot; Next[tot] = head[u]; head[u] = tot; to[tot] = v; }} w, G, sam;struct Query{ int id, l, r; inline bool operator < (const Query& rhs) const{ return r < rhs.r; }} S[M];inline void insert(int k, int op){ p = tail; if(a[p].tranc[k] != 0){ q = a[p].tranc[k]; if(a[q].len == a[p].len + 1) tail = q; else{ a[nq = ++ cnt] = a[q]; a[q].fa = nq; a[nq].len = a[p].len + 1; for(; a[p].tranc[k] == q; p = a[p].fa) a[p].tranc[k] = nq; tail = nq; } } else{ np = ++ cnt; a[np].len = a[tail].len + 1; for(p = tail; p && !a[p].tranc[k]; p = a[p].fa) a[p].tranc[k] = np; if(!p) a[np].fa = 1; else{ q = a[p].tranc[k]; if(a[q].len == a[p].len + 1) a[np].fa = q; else{ a[nq = ++ cnt] = a[q]; a[q].fa = a[np].fa = nq; a[nq].len = a[p].len + 1; for(; a[p].tranc[k] == q; p = a[p].fa) a[p].tranc[k] = nq; } } tail = np; } w.add(tail, op); sam.add(op, tail);}inline void dfs(int x){ in[x] = ++ num; seg[num] = x; for(int i = G.head[x]; i != -1; i = G.Next[i]){ dfs(G.to[i]); } out[x] = num;}inline void change(int x, int d){ for(; x <= cnt; x += (x & -x)) C[x] += d;}inline int ask(int x){ int ret = 0; for(; x > 0; x -= (x & -x)) ret += C[x]; return ret;}inline void dfs2(int x){ v[x] += v[a[x].fa]; for(int i = G.head[x]; i != -1; i = G.Next[i]) dfs2(G.to[i]);}int main(){ int n = read(), lim = read(); cnt = 1; G.init(); w.init(); sam.init(); for(int i = 1; i <= n; i ++){ scanf("%s", s + 1); tail = 1; int len = strlen(s + 1); for(int j = 1; j <= len; j ++){ insert(s[j] - 'a' + 1, i); } } for(int i = 1; i <= cnt; i ++){ if(a[i].fa != 0) G.add(a[i].fa, i); } dfs(1); for(int i = 1; i <= cnt; i ++) S[i] = (Query){i, in[i], out[i]}; sort(S + 1, S + cnt + 1); int k = 1; for(int i = 1; i <= cnt; i ++){ for(int j = w.head[seg[i]]; j != -1; j = w.Next[j]){ if(lastins[w.to[j]]) change(lastins[w.to[j]], -1); change(lastins[w.to[j]] = i, 1); } while(S[k].r == i) sum[S[k].id] = ask(S[k].r) - ask(S[k].l - 1), k ++; } for(int i = 1; i <= cnt; i ++){ if(sum[i] >= lim) v[i] = a[i].len - a[a[i].fa].len; else v[i] = 0; } dfs2(1); LL ans = 0; for(int i = 1; i <= n; i ++){ if(i > 1) printf(" "); ans = 0; for(int j = sam.head[i]; j != -1; j = sam.Next[j]) ans += v[sam.to[j]]; printf("%lld", ans); } return 0;}
0 0
- BZOJ3277——串
- 【bzoj3277&&3474】串
- bzoj3277 串【解法一】
- bzoj3277 串【解法二】
- bzoj3277&&bzoj3473 串(SA+二分+lcp)
- [BZOJ3277]串(后缀数组+二分+st表)
- [bzoj3473][bzoj3277][后缀数组]字符串
- CF204E Little Elephant and Strings(同bzoj3277)
- 数据结构——串
- 数据结构——串
- 串——数据结构
- hdu2203——亲和串
- 数据结构——顺序串
- hdu4545——魔法串
- NYOJ——01串
- 大话数据结构——串
- 反转串——字符
- 数据结构之——串
- 贝叶斯学习及共轭先验
- 2016/5/21 Seperate by *
- BZOJ 2296 【POJ Challenge】随机种子 构造
- Android自定义控件之滑动解锁
- location的解析过程
- BZOJ3277——串
- orace 字段类型变更
- 使用继承的注意点
- HDU 5543 Pick The Sticks 背包变形 ccpc
- 【POJ2774】Long Long Message,第一次的后缀数组
- 【python gensim使用】word2vec词向量处理中文语料
- JavaScript插入 引用 声明变量
- mysql mysql 1045 using password yes
- elasticsearch 的安装使用总结,在ubuntu上