ACdream 1430 SETI 后缀自动机
来源:互联网 发布:淘宝账号注册首页登录 编辑:程序博客网 时间:2024/05/22 08:23
题目大意:
就是对于给定的串S, 长度不超过10000, 求出其有多少种子串T, 使得T在S中至少不重叠地出现了2次以上
大致思路:
很明显的后缀自动机吧, 建立S的后缀自动机, 记录每个节点对应的串出现的最左和最右位置, 以及出现次数, dfs遍历一遍后缀自动机上的点即可了
细节见代码吧
代码如下:
Result : Accepted Memory : 7076 KB Time : 8 ms
/* * Author: Gatevin * Created Time: 2015/5/20 20:29:44 * File Name: Rin_Tohsaka.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;#define foreach(e, x) for(__typeof(x.begin()) e = x.begin(); e != x.end(); ++e)#define SHOW_MEMORY(x) cout<<sizeof(x)/(1024*1024.)<<"MB"<<endl#define maxn 20010#define maxm 10010struct Suffix_Automation{ struct State { State *par; State *go[26]; int right, val, leftmost, rightmost, mi; bool vis; void init(int _val = 0) { par = 0, leftmost = 1e9 + 7, rightmost = -1, val = _val, right = 0, mi = 0; vis = 0; memset(go, 0, sizeof(go)); } }; State *root, *last, *cur; State nodePool[maxn]; void init() { cur = nodePool; root = newState(); last = root; } State* newState(int val = 0) { cur->init(val); return cur++; } void extend(int w, int pos) { State *p = last; State *np = newState(p->val + 1); np->right = 1; np->leftmost = pos, np->rightmost = pos; while(p && p->go[w] == 0) { p->go[w] = np; p = p->par; } if(p == 0) { np->par = root; } else { State *q = p->go[w]; if(p->val + 1 == q->val) { np->par = q; } else { State *nq = newState(p->val + 1); memcpy(nq->go, q->go, sizeof(q->go)); nq->par = q->par; q->par = nq; np->par = nq; while(p && p->go[w] == q) { p->go[w] = nq; p = p->par; } } } last = np; } State* b[maxn]; int d[maxm]; void topo() { int cnt = cur - nodePool; int maxVal = 0; memset(d, 0, sizeof(d)); for(int i = 1; i < cnt; i++) maxVal = max(maxVal, nodePool[i].val), d[nodePool[i].val]++; for(int i = 1; i <= maxVal; i++) d[i] += d[i - 1]; for(int i = 1; i < cnt; i++) b[d[nodePool[i].val]--] = &nodePool[i]; b[0] = root; } void info() { int cnt = cur - nodePool; State *p; for(int i = cnt - 1; i > 0; i--) { p = b[i]; p->par->right += p->right; p->mi = p->par->val + 1; p->par->leftmost = min(p->par->leftmost, p->leftmost); p->par->rightmost = max(p->par->rightmost, p->rightmost); } } int ans; void dfs(State *now) { now->vis = 1; if(now->right >= 2 && now != root) { int len2 = now->rightmost - now->leftmost; if(now->val <= len2) ans += now->val - now->mi + 1; else if(now->mi <= len2) ans += len2 - now->mi + 1; } for(int i = 0; i < 26; i++) if(now->go[i] && !now->go[i]->vis) dfs(now->go[i]); return; } void solve() { ans = 0; dfs(root); printf("%d\n", ans); }};Suffix_Automation sam;char in[10010];int main(){ while(scanf("%s", in) != EOF) { int len = strlen(in); sam.init(); for(int i = 0; i < len; i++) sam.extend(in[i] - 'a', i); sam.topo(); sam.info(); sam.solve(); } return 0;}
0 0
- ACdream 1430 SETI 后缀自动机
- Acdream 1430 SETI(后缀数组)
- ACdream 1430 SETI 后缀自动机/后缀数组 不重叠子串的个数
- acdream OJ 1430 SETI 后缀数组
- acdream 1430 SETI 后缀数组+height分组
- ACdream 1430 SETI
- ACdream 1430 【后缀数组+分组】
- SETI--后缀数组
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机)
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- win32使用ATL显示C#COM窗体
- 【陈式兔子定理】本科生、硕士生、博士生、博士后之区别
- css中的:before 和 :after
- android摇一摇
- 【C++注意事项】2 变量声明和定义
- ACdream 1430 SETI 后缀自动机
- Oracle使用APEX与ADF快速开发漂亮的WEB应用
- Android UI 之一步步教你自定义控件(自定义属性、合理设计onMeasure、合理设计onDraw等)
- 【Java】Java集合框架源码和数据结构简要分析——List
- Intellij IDEA搭建Android Wear开发环境(Windows环境,含创建模拟器)
- 计算机学习总结
- poj 1163/3176 数字三角形【简单DP】
- POJ 3468 【线段树区间更新-成段更新】
- java终结处理和垃圾回收