【后缀自动机】 HDOJ 5431 AB String
2015-09-06 16:20
274 查看
在sam上做dp统计有多少的串不是a的子串,然后找到长度,dfs找串就行了。。
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int alpha = 2; const int maxn = 40005; const int maxm = 30; struct node { int len; LL cnt[maxm]; node *fa, *ch[alpha]; }pool[maxn], *last, *root; vector<int> ans; char s[maxn]; int a[maxn]; int tot; node* newnode(int len) { node *p = &pool[tot++]; p->len = len; p->fa = 0; memset(p->ch, 0, sizeof p->ch); return p; } void init() { tot = 0; root = last = newnode(0); } void add(int c) { node *p = last, *np = newnode(p->len + 1); last = np; for(; p && !p->ch[c]; p = p->fa) p->ch[c] = np; if(!p) np->fa = root; else { node *q = p->ch[c]; if(q->len == p->len + 1) np->fa = q; else { node *nq = newnode(p->len + 1); *nq = *q; nq->len = p->len + 1; np->fa = q->fa = nq; for(; p && p->ch[c] == q; p = p->fa) p->ch[c] = nq; } } } int C[maxn]; node *tp[maxn]; LL two[100]; void Tp() { memset(C, 0, sizeof C); for(int i = 0; i < tot; i++) C[pool[i].len]++; for(int i = 1; i < tot; i++) C[i] += C[i-1]; for(int i = 0; i < tot; i++) tp[--C[pool[i].len]] = &pool[i]; } void solve(int& K, int cnt) { K--; for(int i = 1; i <= cnt; i++) { a[i] = K % 2; K /= 2; } for(int i = cnt; i >= 1; i--) ans.push_back(a[i] + 'A'); } void dfs(node *o, int& K, int pos) { if(K <= 0) return; if(pos == 0) return; for(int i = 0; i < alpha; i++) { if(o->ch[i]) { if(K <= o->ch[i]->cnt[pos-1]) { ans.push_back(i + 'A'); dfs(o->ch[i], K, pos-1); return; } else K -= o->ch[i]->cnt[pos-1]; } else { if(K <= two[pos-1]) { ans.push_back(i + 'A'); if(pos - 1) solve(K, pos - 1); return; } else K -= two[pos-1]; } } } void work() { scanf("%s", s); for(int i = 0; s[i]; i++) add(s[i] - 'A'); Tp(); two[0] = 1; for(int i = 1; i <= 40; i++) two[i] = (1LL << i); for(int i = tot - 1; i >= 0; i--) { tp[i]->cnt[0] = 0; for(int j = 1; j < maxm; j++) { tp[i]->cnt[j] = 0; for(int k = 0; k < alpha; k++) { if(tp[i]->ch[k]) tp[i]->cnt[j] += tp[i]->ch[k]->cnt[j-1]; else tp[i]->cnt[j] += two[j - 1]; } } } int m, K; scanf("%d", &m); while(m--) { scanf("%d", &K); int tlen; for(tlen = 1;; tlen++) { if(root->cnt[tlen] < K) K -= root->cnt[tlen]; else break; } ans.clear(); dfs(root, K, tlen); for(int i = 0; i < ans.size(); i++) printf("%c", ans[i]); printf("\n"); } } int main() { int _; scanf("%d", &_); while(_--) { init(); work(); } return 0; }
相关文章推荐
- spring事务使用+常见出错解决方案
- Python+OpenCV学习(1)---图像的读取与保存
- 计算两点之间连线的一半长度
- dd备份文件系统
- hiho#1033 : 交错和
- ubuntu如何完全卸载Java
- 《打造Facebook》读书笔记之Facebook的产品开发流程
- 【Intellji 14.1.4下 中文注释乱码 & 控制台输出中文乱码 问题的解决方案
- XStream日期转换,注解转换
- Swift UIButton设置动态图片
- 计算两点中的中点
- 集训回顾
- HDU 1686 Oulipo(KMP算法 字符串匹配)
- ubuntu默认进入命令行
- hdu 1204 糖果大战(概率问题 markov 过程)
- Java程序运行机制
- Redhat 6.6 + Qt5.5 编译QOCI驱动
- Functional reactive programming introduction using ReactiveCocoa中文版
- [华为oj]24点问题
- 检查所有实体的编号是否重复