【后缀自动机】poj1509 Glass Beads
字符串最小表示 后缀自动机 O(n)
把串复制一次,链接在后面之后,建立SAM,贪心地在SAM上转移,每次贪心地选择最小的字符,转移的长度为n时停止。
输出时由于要最靠前的,所以要在endpos集合中挑一个最小的,这个在slink_tree上递推一下就能轻松获得。
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- using namespace std;
- #define MAXL 10000
- #define MAXC 26
- int v[2*MAXL+10],__next[2*MAXL+10],first[2*MAXL+10],e;
- void AddEdge(int U,int V){
- v[++e]=V;
- __next[e]=first[U];
- first[U]=e;
- }
- char s[MAXL*2+10];//文本串
- int len/*文本串长度*/;
- struct SAM{
- int minendpos[2*MAXL+10];
- int n/*状态数0~n-1*/,maxlen[2*MAXL+10],minlen[2*MAXL+10],trans[2*MAXL+10][MAXC],slink[2*MAXL+10];
- void clear(){
- memset(maxlen,0,sizeof(maxlen));
- memset(minlen,0,sizeof(minlen));
- memset(trans,0,sizeof(trans));
- memset(slink,0,sizeof(slink));
- memset(minendpos,0x7f,sizeof(minendpos));
- n=0;
- }
- int new_state(int _maxlen,int _minlen,int _trans[],int _slink){
- maxlen[n]=_maxlen;
- minlen[n]=_minlen;
- for(int i=0;i<MAXC;++i){
- if(_trans==NULL){
- trans[n][i]=-1;
- }
- else{
- trans[n][i]=_trans[i];
- }
- }
- slink[n]=_slink;
- return n++;
- }
- int add_char(char ch,int u,int pos){
- if(u==-1){
- return new_state(0,0,NULL,-1);
- }
- int c=ch-'a';
- int z=new_state(maxlen[u]+1,-1,NULL,-1);
- minendpos[z]=pos;
- int v=u;
- while(v!=-1 && trans[v][c]==-1){
- trans[v][c]=z;
- v=slink[v];
- }
- if(v==-1){//最简单的情况,suffix-path(u->S)上都没有对应字符ch的转移
- minlen[z]=1;
- slink[z]=0;
- return z;
- }
- int x=trans[v][c];
- if(maxlen[v]+1==maxlen[x]){//较简单的情况,不用拆分x
- minlen[z]=maxlen[x]+1;
- slink[z]=x;
- return z;
- }
- int y=new_state(maxlen[v]+1,-1,trans[x],slink[x]);//最复杂的情况,拆分x
- slink[y]=slink[x];
- minlen[x]=maxlen[y]+1;
- slink[x]=y;
- minlen[z]=maxlen[y]+1;
- slink[z]=y;
- int w=v;
- while(w!=-1 && trans[w][c]==x){
- trans[w][c]=y;
- w=slink[w];
- }
- minlen[y]=maxlen[slink[y]]+1;
- return z;
- }
- void dfs(int U){
- for(int i=first[U];i;i=__next[i]){
- dfs(v[i]);
- minendpos[U]=min(minendpos[U],minendpos[v[i]]);
- }
- }
- void work_slink_tree(){
- for(int i=1;i<n;++i){
- AddEdge(slink[i],i);
- }
- dfs(0);
- }
- }sam;
- int T;
- int main(){
- // freopen("poj1509.in","r",stdin);
- scanf("%d",&T);
- for(;T;--T){
- sam.clear();
- scanf("%s",s);
- len=strlen(s);
- for(int i=0;i<len-1;++i){
- s[i+len]=s[i];
- }
- int U=sam.add_char(0,-1,0);
- for(int i=0;i<len*2-1;++i){
- U=sam.add_char(s[i],U,i);
- }
- U=0;
- for(int i=0;i<len;++i){
- for(int j=0;j<MAXC;++j){
- if(sam.trans[U][j]!=-1){
- U=sam.trans[U][j];
- break;
- }
- }
- }
- printf("%d\n",sam.minendpos[U]-len+2);
- }
- return 0;
- }
【后缀自动机】poj1509 Glass Beads的更多相关文章
- POJ1509 Glass Beads(最小表示法 后缀自动机)
Time Limit: 3000MS Memory Limit: 10000K Total Submissions: 4901 Accepted: 2765 Description Once ...
- POJ1509 Glass Beads
Glass Beads Time Limit: 3000MS Memory Limit: 10000K Total Submissions: 4314 Accepted: 2448 Descr ...
- POJ1509 Glass Beads [后缀自动机]
题意: 给一个字符串S,每次可以将它的第一个字符移到最后面,求这样能得到的字典序最小的字符串.输出开始下标 练习SAM第一题! SS构造SAM,然后从开始尽量走最小走n步就可以啦 什么?开始位置?!R ...
- POJ1509 Glass Beads 【后缀自动机】
题目分析: 模板练手.看最长能走多远. 代码: #include<iostream> #include<cstdio> #include<cstdlib> #inc ...
- [POJ1509]Glass Beads 后缀自动机 最小循环串
题目链接:http://poj.org/problem?id=1509 题目意思就是求循环字符串的最小表示. 我们用字符串S+S建立SAM,然后从root开始走n步,每次尽量选最小的. 由于 SAM ...
- [poj1509]Glass Beads(最小表示法)
题目大意:求循环同构的字符串的最小字典序. 解题关键:最小表示法模板题. #include<cstdio> #include<cstring> #include<algo ...
- 【POJ1509】Glass Beads 【后缀自动机】
题意 给出一个字符串,求它的最小表示法. 分析 这个题当然可以用最小表示法做啦!但是我是为了学后缀自动机鸭! 我们把这个字符串长度乘二,然后建SAM,然后在SAM上每次跑最小的那个字母,找出长度为n的 ...
- UVA 719 / POJ 1509 Glass Beads (最小表示法/后缀自动机)
题目大意: 给出一个长度为N的字符串,求其字典序最小的循环同构. N<=10W. 算法讨论: 算法一.最小表示法.定义题. 算法二.后缀自动机. Codes: #include <iost ...
- POJ 1509 Glass Beads 后缀自动机 模板 字符串的最小表示
http://poj.org/problem?id=1509 后缀自动机其实就是一个压缩储存空间时间(对节点重复利用)的储存所有一个字符串所有子串的trie树,如果想不起来长什么样子可以百度一下找个图 ...
随机推荐
- 20151024_004_C#基础知识(C#中的访问修饰符,继承,new关键字,里氏转换,is 和 as,多态,序列化与反序列化)
1:C#中的访问修饰符 public: 公共成员,完全公开,没有访问限制. private: 私有的,只能在当前类的内部访问. protected: 受保护的,只能在当前类的内部以及该类的子类中访问. ...
- webstorm vue环境设置
1. 首先安装vue插件,安装方法: setting --> plugin ,点击plugin,在内容部分的左侧输入框输入vue,会出现两个关于vue的插件,点击安装即可.安装完成后,就可 ...
- js_md5加密和base64的加密解密
1.最近有些人在爬我们公司的数据,然有了这个md5加密的小需求.为什么叫小需求呢?嗯,之前没做过,会以为很复杂. 其实,是想多了. 2.前端md5加密,其实也并不是安全的,因为代码是可见的.也就是说, ...
- C++学习之路(六):实现一个String类
直接贴代码吧,这段时间准备面试也正好练习了一下. class String { public: String(const char *str = ""); ~String(void ...
- C++之容器
容器,迭代器与容器适配器 所谓容器,即是将最常运用的一些数据结构(data structures)用类模板实现出来,用于容纳特定类型的对象.根据数据在容器中排列的特性,容器可概分为序列式(sequen ...
- perl_nc.pl
#!/usr/bin/perl use strict; use IO::Socket; use IO::Select; use Getopt::Std; my %option;getopts('lp: ...
- python的时间和日期--time、datetime应用
time >>> import time >>> time.localtime() #以time.struct_time类型,打印本地时间 time.struct_ ...
- pypcap 安装
1.下载winpcap开发包 https://www.winpcap.org/devel.htm 下载https://github.com/pynetwork/pypcap/releases最新发布的 ...
- linux命令(43):cal命令
cal命令可以用来显示公历(阳历)日历.公历是现在国际通用的历法,又称格列历,通称阳历.“阳历”又名“太阳历”,系以地球绕行太阳一周为一年,为西方各国所通用,故又名“西历”. 1.命令格式: cal ...
- jpa缓存导致无法查询到更新后的数据&android出现ANR的一个解决办法
1. 向服务器更新记录后查询,始终查询不到更新后的信息 只能查到更新之前的,马上推断出是缓存的问题.网上搜索一番,将问题定位为jpa缓存,我们要设置jpa查询时不从缓存中取,直接从数据库中取,这样便能 ...