hdu 4641 K-string(后缀自动机 + 并查集)
来源:互联网 发布:iea数据库 编辑:程序博客网 时间:2024/06/13 09:41
题目链接:hdu 4641 K-string
代码
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long ll;const int maxn = 300005;const int SIGMA_SIZE = 26;struct SAM { int sz, last; int g[maxn<<1][SIGMA_SIZE], pre[maxn<<1], step[maxn<<1]; int pos[maxn<<1], right[maxn<<1], cnt[maxn<<1]; int ridx[maxn<<1]; void newNode(int s) { step[++sz] = s; pre[sz] = 0; memset(g[sz], 0, sizeof(g[sz])); } int idx(char ch) { return ch -'a'; } void init() { sz = 0, last = 1; newNode(0); } void insert(char ch); void get_tuopu(); void get_right(char* str); int f[maxn<<1], sub[maxn<<1]; int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); } ll ans[maxn]; void solve(int m, int* op, int k);}SA;int N, M, K, op[maxn];char str[maxn];void init () { SA.init(); scanf("%s", str); for (int i = 0; i < N; i++) SA.insert(str[i]); char tmp[5]; for (int i = 1; i <= M; i++) { scanf("%d", &op[i]); if (op[i] == 1) { scanf("%s", tmp); str[N++] = tmp[0]; SA.insert(tmp[0]); } } str[N] = '\0'; SA.get_tuopu(); SA.get_right(str);}int main () { while (scanf("%d%d%d", &N, &M, &K) == 3) { init(); SA.solve(M, op, K); } return 0;}void SAM::solve(int m, int* op, int k) { ll ret = 0; for (int i = 0; i < sz; i++) { int u = pos[i]; if (right[u] >= k) ret += step[u] - step[pre[u]]; } for (int i = 0; i <= sz; i++) f[i] = i, sub[i] = 0; for (int i = m; i; i--) { if (op[i] == 2) ans[i] = ret; else { int p = ridx[N--]; int fp = find(p); while (fp && right[fp] < k) { p = f[fp] = pre[fp]; fp = find(p); } if (fp == 0) continue; sub[fp]++; while (fp && right[fp] - sub[fp] < k) { ret -= step[fp] - step[pre[fp]]; p = f[fp] = pre[fp]; sub[pre[fp]] += sub[fp]; fp = find(p); } } } for (int i = 1; i <= m; i++) if (op[i] == 2) printf("%lld\n", ans[i]);}void SAM::insert(char ch) { newNode(step[last] + 1); int v = idx(ch), p = last, np = sz; ridx[N] = np; // while (p && !g[p][v]) { g[p][v] = np; p = pre[p]; } if (p) { int q = g[p][v]; if (step[q] == step[p] + 1) pre[np] = q; else { newNode(step[p] + 1); int nq = sz; for (int j = 0; j < SIGMA_SIZE; j++) g[nq][j] = g[q][j]; pre[nq] = pre[q]; pre[np] = pre[q] = nq; while (p && g[p][v] == q) { g[p][v] = nq; p = pre[p]; } } } else pre[np] = 1; last = np;}void SAM::get_tuopu() { for (int i = 0; i <= sz; i++) cnt[i] = 0; for (int i = 1; i <= sz; i++) cnt[step[i]]++; for (int i = 1; i <= sz; i++) cnt[i] += cnt[i-1]; for (int i = 1; i <= sz; i++) pos[cnt[step[i]]--] = i; }void SAM::get_right(char* str) { int p = 1, n = strlen(str); for (int i = 0; i <= sz; i++) right[i] = 0; for (int i = 0; i < n; i++) { int v = idx(str[i]); p = g[p][v]; right[p]++; } for (int i = sz; i; i--) { int u = pos[i]; right[pre[u]] += right[u]; }}
0 0
- hdu 4641 K-string(后缀自动机 + 并查集)
- hdu4641 K-string,后缀自动机,并查集
- 【后缀自动机】[HDU 4641]K-string
- hdu4641-K-string(后缀自动机)
- HDU 4641 K-string 2013年多校第4场J题 后缀自动机
- 2017沈阳网络赛 1001 HDU 6194 string string string(后缀自动机 出现k次的子串个数)
- HDU 4622(后缀自动机)
- HDU 4436(后缀自动机)
- hdu 5008 Boring String Problem(后缀自动机构造后缀树)
- zoj 3891 K-hash(后缀自动机)
- HDU 4641 至少出现K次本质不同子串数:后缀自动机
- HDU 6194 string string string :后缀数组+单调队列 | 后缀自动机
- K - Cube Stacking(并查集)
- hdu 4436 str2int(后缀自动机)
- HDU 4622 Reincarnation(后缀自动机)
- hdu 4622(后缀自动机)
- HDU 4622 后缀自动机
- HDU 4622 后缀自动机
- Eclipse查找替换巧妙技巧用法
- DEPRECATED: Use of this script to execute hdfs command is deprecated.
- Coolite ComboBox中显示树
- 图形化控制台连接mysql报错1042解决办法
- 没有躲过的坑--获取一张图片的width和height
- hdu 4641 K-string(后缀自动机 + 并查集)
- [02](面向对象的)思想
- VS2010实现自动添加版权信息
- OpenCV中保存视频的一般方法
- 从头认识java-8.8 使用匿名内部类改造7.8章节的工厂方法
- 浏览器 HTTP 缓存原理分析
- Android卡片新闻页优化实践
- 营业执照号码生成规则
- hdu 4681 String(LIS+暴力)