hdu4416——后缀自动机
来源:互联网 发布:知乎书单 编辑:程序博客网 时间:2024/06/05 06:52
题意:问给定的字符串(S)有多少个不同的子串满足不是另外给定的一组字符串(T1~Tn)中任何一个串的子串。
把T中的字符串依次拿去和S的自动机匹配。每次匹配到一个状态,更新这个状态所匹配的最大的长度p,那么这个状态所表示的子串中长度大于p的即为我们要找的。在计算答案的时候,我们还要同时更新目前状态的pre状态的p值,所以要按逆拓扑序计算总答案。
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#define lng long longusing namespace std;const int maxn = 200000 + 10;int str[maxn];int len;struct suffix_automaton{ int ch[maxn][27], pre[maxn], val[maxn]; int c[maxn], top[maxn], p[maxn]; int sz, last; void init() { pre[0] = -1; last = 0; sz = 1; memset(ch[0], 0, sizeof(ch[0])); memset(p, 0, sizeof(p)); } void insert(int x) { int p = last, np = sz++; last = np; memset(ch[np], 0, sizeof(ch[np])); val[np] = val[p] + 1; while(p != -1 && ch[p][x] == 0) { ch[p][x] = np; p = pre[p]; } if(p == -1) pre[np] = 0; else { int q = ch[p][x]; if(val[q] == val[p] + 1) pre[np] = q; else { int nq = sz++; memcpy(ch[nq], ch[q], sizeof(ch[q])); val[nq] = val[p] + 1; pre[nq] = pre[q]; pre[q] = pre[np] = nq; while(p != -1 && ch[p][x] == q) { ch[p][x] = nq; p = pre[p]; } } } } void update(char * s) { int l = 0, u = 0; for(int i = 0; s[i]; ++i) { int x = s[i] - 'a'; if(ch[u][x]) { u = ch[u][x]; l++; } else { while(u != -1 && ch[u][x] == 0) u = pre[u]; if(ch[u][x]) { l = val[u]; u = ch[u][x]; l++; } else u = 0, l = 0; } p[u] = max(p[u], l); } } void solve() { memset(c, 0, sizeof(c)); for(int i = 0; i < sz; ++i) c[val[i]] += 1; for(int i = 1; i <= len; ++i) c[i] += c[i - 1]; for(int i = 0; i < sz; ++i) top[--c[val[i]]] = i; lng ans = 0; for(int i = sz - 1; i > 0; --i) { int u = top[i]; if(p[u] < val[u]) { int tmp = max(p[u], val[pre[u]]); ans += val[u] - tmp; } p[pre[u]] = max(p[pre[u]], p[u]); } printf("%I64d\n", ans); } }sam;char s[maxn];void prework(){ int q; scanf("%d", &q); scanf("%s", s); len = strlen(s); sam.init(); for(int i = 0; i < len; ++i) { str[i] = s[i] - 'a'; sam.insert(str[i]); } while(q--) { scanf("%s", s); sam.update(s); }}void solve(){ sam.solve();}int main(){ freopen("in.txt", "r", stdin); int t; cin >> t; int cc = 1; while(t--) { prework(); printf("Case %d: ", cc++); solve(); } return 0;}
- hdu4416——后缀自动机
- HDU4416(后缀自动机)
- hdu4416[多串后缀自动机]
- 【后缀自动机】SPOJLCS SPOJNSUBSTR SPOJLCS2 HDU4416
- 【后缀自动机】SPOJLCS SPOJNSUBSTR SPOJLCS2 HDU4416
- 后缀自动机(不同子串的个数)hdu4416
- 后缀自动机小练总结(Spoj1811&&Hdu4416&&CodeForces235C)
- hdu3518——后缀自动机
- CF149E——后缀自动机
- 后缀自动机————入门
- SAM 后缀自动机——学习笔记
- hdu4416
- 【HDU4416】Good Article Good sentence【后缀数组】
- codeforces Round #92 D——后缀自动机
- Codeforces Beta Round #93 D. Password——后缀自动机
- 字符串处理——后缀自动机の板子
- 后缀数组/AC自动机——BZOJ3172 [Tjoi2013]单词
- 后缀自动机
- 关于STL常用容器的erase使用陷阱
- DocumentInteraction Controllerl的使用
- 座右铭-激励自己的话
- 关于Android中popupwindow的listview的item点击事件无效的解决方案
- 2013年8月5日
- hdu4416——后缀自动机
- 网站优化必须要原创么 新手SEO更要注重理解
- java 几率实现以55%的几率生成3
- XML 布局 与相关例子
- POJ 1659-Frog's Neighborhood
- WSO2-Stratos2.0简介
- 手Q游戏中心上线 完美释放娱乐基因
- javascript用正则表达式过滤空格
- Thinking in java学习1