SPOJ SUBLEX Lexicographical Substring Search
来源:互联网 发布:爱淘宝 编辑:程序博客网 时间:2024/05/19 05:34
SPOJ SUBLEX Lexicographical Substring Search
SAM,后缀自动机,计数
题意
给一个字符串S,将他的所有子串(去重)按字典序排序,给q个询问,问拍第k个子串是谁。
思路
后缀自动机的计数问题。后缀自动机每个状态都代表一个或几个字符串。统计每个节点能到达多少个跟他具有相同前缀的字符串。
换句话说就是统计每个点通过trans边能到多少个串。方法可以dfs,也可以基排。基排就是处理出拓扑序后从后往前更新。
处理好subamo数组后,查找时尽量走小的边。就获得了最终rank(k)的字符串。
代码
#include <bits/stdc++.h>#define M(a,b) memset(a,b,sizeof(a))typedef long long LL;using namespace std;const int MAXL=100005;const int MAXS=26;struct SAM{ int n, len, st; int maxlen[2*MAXL+10], minlen[2*MAXL+10], trans[2*MAXL+10][MAXS], slink[2*MAXL+10], subamo[2*MAXL+10]; int new_state(int _maxlen, int _minlen, int* _trans, int _slink) { n++; maxlen[n]=_maxlen; minlen[n]=_minlen; subamo[n]=1; for(int i=0; i<MAXS; i++) { if(_trans==NULL) trans[n][i]=0; else trans[n][i]=_trans[i]; } slink[n]=_slink; return n; } int add_char(char ch, int u) { int c=ch-'a'; int z=new_state(maxlen[u]+1, -1, NULL, 0); int v=u; while(v!=0&&trans[v][c]==0) { trans[v][c]=z; v=slink[v]; } if(v==0) { minlen[z]=1; slink[z]=1; return z; } int x=trans[v][c]; if(maxlen[v]+1==maxlen[x]) { minlen[z]=maxlen[x]+1; slink[z]=x; return z; } int y=new_state(maxlen[v]+1, -1, trans[x], slink[x]); minlen[x]=maxlen[y]+1; slink[x]=y; minlen[z]=maxlen[y]+1; slink[z]=y; int w=v; while(w!=0&&trans[w][c]==x) { trans[w][c]=y; w=slink[w]; } minlen[y]=maxlen[slink[y]]+1; return z; } void init() { memset(maxlen, 0, sizeof(maxlen)); memset(minlen, 0, sizeof(maxlen)); memset(trans, 0, sizeof(maxlen)); memset(slink, 0, sizeof(maxlen)); n=0; st=new_state(0, -1, NULL, 0); } void addstring(char* s, int len) { int la=st; for(int i=0;i<len;i++) { la=add_char(s[i], la); } this->len=len; } int ji[MAXL+10], id[2*MAXL+10]; void prepare() { memset(ji, 0, sizeof(ji)), memset(id, 0, sizeof(id)); ji[0]=0; for(int i=st;i<=n;i++) ji[maxlen[i]]++; for(int i=1;i<=n;i++) ji[i]+=ji[i-1]; for(int i=st;i<=n;i++) id[ji[maxlen[i]]--]=i; for(int i=n;i>=st;i--) { int now=id[i]; for(int j=0;j<MAXS;j++) { if(trans[now][j]) subamo[now]+=subamo[trans[now][j]]; } } } void deal(int k) { int now=this->st; string s=""; while(k&&now) { for(int i=0;i<MAXS;i++) { if(trans[now][i]) { int to=trans[now][i]; if(subamo[to]>=k) { s.push_back('a'+i); now=to; k--; break; } else { k-=subamo[to]; } } } } printf("%s\n", s.c_str()); }}sam;char s[MAXL];int main(){ scanf("%s", s);int n=strlen(s); sam.init(); sam.addstring(s, n); sam.prepare(); int q;scanf("%d", &q); while(q--) { int k;scanf("%d", &k); sam.deal(k); } //system("pause"); return 0;}
阅读全文
0 0
- SPOJ SUBLEX Lexicographical Substring Search
- SPOJ SUBLEX Lexicographical Substring Search
- SPOJ SUBLEX 7258. Lexicographical Substring Search
- SPOJ SUBLEX Lexicographical Substring Search 后缀自动机
- 【后缀自动机】[SPOJ SUBLEX]Lexicographical Substring Search
- SPOJ 7258 SUBLEX - Lexicographical Substring Search (后缀自动机)
- [SPOJ7258]SUBLEX - Lexicographical Substring Search
- spoj7258 Lexicographical Substring Search(SUBLEX) 后缀自动机
- SPOJ 题目7528 SUBLEX - Lexicographical Substring Search(后缀自动机求排名k的子串)
- SPOJ 7258 SUBLEX - Lexicographical Substring Search【SAM,我要报警x
- spoj7258 Lexicographical Substring Search(SUBLEX),后缀自动机
- [SPOJ7258]SUBLEX - Lexicographical Substring Search(后缀自动机)
- spoj 7258 Lexicographical Substring Search (后缀自动机)
- SPOJ Lexicographical Substring Search --后缀自动机
- SPOJ Lexicographical Substring Search 后缀自动机
- spoj 7258 Lexicographical Substring Search (后缀自动机+dp)
- spoj 7258 Lexicographical Substring Search(后缀数组 | 后缀自动机)
- SPOJ SUBLEX
- 机器学习的归宿《终极算法》·一
- sql,用COALESCE,NULLIF对空值和null值进行处理
- QT C++中实现打印QString
- 点击图片放大
- JavaScript事件冒泡
- SPOJ SUBLEX Lexicographical Substring Search
- 2017.09.26 systemView 查看 freeRTOS 任务运行情况
- linux中后台进程管理
- 树莓派开发系列教程9——树莓派GPIO控制
- 利用Git Shell来进行与Github的远程交互
- 文章标题
- 被忽略的Spring3小改进—支持多数据源的@Transactional事务注解
- input输入字符限制
- Qt获取当前时间的两种方式笔记