后缀自动机小结 (spoj 8222)
来源:互联网 发布:手机语音拨号软件 编辑:程序博客网 时间:2024/06/05 11:12
后缀自动机理解关键点:
1. 根到任意一个结点都可以形成S的一个子串,并且S的所有子串都可以通过这种方式形成;
2. 到达该节点是所有路径就是一个right集合,一个拥有相同后缀的right集合;
3. 设某子串为str,这后缀自动机读入str后能到达的状态为right(str),即str在S中出现的位置的集合;
4. 假设node[b].fa = a,则状态a可以代替状态b进行识别。
附图:
更详细的资料:
http://wenku.baidu.com/view/90f22eec551810a6f4248606.html
http://blog.sina.com.cn/s/blog_7812e98601012cim.html
例题:
spoj 8222
题意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值。求F(1)..F(Length(S))。
限制:|S| <= 250000
1. 根到任意一个结点都可以形成S的一个子串,并且S的所有子串都可以通过这种方式形成;
2. 到达该节点是所有路径就是一个right集合,一个拥有相同后缀的right集合;
3. 设某子串为str,这后缀自动机读入str后能到达的状态为right(str),即str在S中出现的位置的集合;
4. 假设node[b].fa = a,则状态a可以代替状态b进行识别。
附图:
更详细的资料:
http://wenku.baidu.com/view/90f22eec551810a6f4248606.html
http://blog.sina.com.cn/s/blog_7812e98601012cim.html
例题:
spoj 8222
题意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值。求F(1)..F(Length(S))。
限制:|S| <= 250000
/*spoj 8222 题意: 给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值。求F(1)..F(Length(S))。 限制: |S| <= 250000 思路: 后缀自动机 后缀自动机理解关键点: 1. 根到任意一个结点都可以形成S的一个子串,并且S的所有子串都可以通过这种方式形成; 2. 到达该节点是所有路径就是一个right集合,一个拥有相同后缀的right集合; 3. 设某子串为str,这后缀自动机读入str后能到达的状态为right(str),即str在S中出现的位置的集合; 4. 假设node[b].fa = a,则状态a可以代替状态b进行识别。 */#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;const int N = 250005;//注意,后缀自动机的节点要开2倍n,根是从1开始的struct SAM {struct Node {int fa, ch[27];int val, ans;void init() {fa = 0;memset(ch, 0, sizeof(ch));val = 0;ans = 0;}} node[2 * N];int tot;int new_node() {node[++tot].init();return tot;}int root, last;void init() {tot = 1;root = last = 1;node[0].init();node[root].init();}void add(int x) {int p = last;int np = new_node(); node[np].val = node[p].val + 1;while(p && node[p].ch[x] == 0)node[p].ch[x] = np, p = node[p].fa;if(p == 0)node[np].fa = root;else {int q = node[p].ch[x];if(node[p].val + 1 == node[q].val)node[np].fa = q;else {int nq = new_node(); node[nq].val = node[p].val + 1;memcpy(node[nq].ch, node[q].ch, sizeof(node[nq].ch));node[nq].fa = node[q].fa;node[q].fa = node[np].fa = nq;while(p && node[p].ch[x] == q)node[p].ch[x] = nq, p = node[p].fa;}}last = np;}void debug() {for(int i = 1; i <= tot; ++i) {printf("id=%d, fa=%d, step=%d, ch=[ ", i, node[i].fa, node[i].val);for(int j = 0; j < 26; ++j) {if(node[i].ch[j])printf("%c,%d ", j+'a', node[i].ch[j]);}puts("]");}}void gao(int);}sam;char str[N];int du[2 * N];int cnt[2 * N];int ans[N];void init() {sam.init();memset(du, 0, sizeof(du));memset(ans, 0, sizeof(ans));memset(cnt, 0, sizeof(cnt));}int que[2 * N], fr, ta;void SAM::gao(int n) {for(int i = 1; i <= tot; ++i) {++du[node[i].fa];}int tmp = root;for(int i = 0; i < n; ++i) {tmp = node[tmp].ch[str[i] - 'a'];cnt[tmp] = 1;}fr = ta = 0;for(int i = 1; i <= tot; ++i) {if(du[i] == 0) {que[ta++] = i;}}while(fr != ta) {int now = que[fr++];--du[node[now].fa];cnt[node[now].fa] += cnt[now];if(du[node[now].fa] == 0) {que[ta++] = node[now].fa;}}for(int i = 2; i <= tot; ++i) {ans[node[i].val] = max(ans[node[i].val], cnt[i]);}for(int i = n - 1; i >= 1; --i) {ans[i] = max(ans[i], ans[i + 1]);}for(int i = 1; i <= n; ++i) {printf("%d\n", ans[i]);}}int main() {while(gets(str)) {int n = strlen(str);init();for(int i = 0; i < n; ++i)sam.add(str[i] - 'a');//sam.debug();sam.gao(n);}return 0;}
0 0
- 后缀自动机小结 (spoj 8222)
- SPOJ 8222 [后缀自动机]
- spoj 8222 Substrings (后缀自动机)
- SPOJ 8222 NSUBSTR 后缀自动机
- spoj 8222 substrings 【后缀自动机】
- spoj 8222 Substrings(NSUBSTR),后缀自动机
- spoj 8222 Substrings (后缀自动机+dp)
- spoj 8222 Substrings(后缀自动机)
- bzoj 2946/Spoj 8222 后缀自动机
- SPOJ 8222 NSUBSTR - Substrings (后缀自动机)
- [后缀自动机 模板题] SPOJ 8222 Substrings
- SPOJ 8222 Substrings 后缀自动机入门
- SPOJ LCS --后缀自动机
- SPOJ LCS2 --后缀自动机
- SPOJ Substrings --后缀自动机
- 【后缀自动机】 SPOJ LCS
- 【后缀自动机】 SPOJ LCS2
- 【后缀自动机】 SPOJ NSUBSTR
- hadoop学习笔记 Hive的cli与Commands
- run ceph in docker
- MUI 的学习与使用
- Unity3D-重新编译Mono加密DLL
- java Collections.sort()实现List排序的默认方法和自定义方法
- 后缀自动机小结 (spoj 8222)
- 219Contains Duplicate II
- Testlink和mantis整合
- Autolayout下设置多个View等比例排列
- TCP流量控制与拥塞控制
- 【干货】产品经理每日必看的数据统计表
- 整理整理生产者消费者模式,用通俗的话描述
- 这些技术都是我们技术人绕不过去的坎
- OC内存管理之—自动释放池