HDU 4270 SAM 后缀自动机
2015-03-30 22:20
267 查看
题目:给出一个串,有3种操作,
操作1:在原串后面,添加一个串
操作2:查询长度为len的子串或者长度小于等于len的后缀中字典序最小的
操作3:删除最后的len个字符
关于删除
首先明确一点: 新建的点只与模板点有关系
由新加入的点7产生的点8是根据点3为模板进行复制的(复制所有信息,包括位置)。那么点8是有点3控制的。
可以从两个图看出,删除点7,不删除点8也是可以达到第一个图的效果。
只是图不是最简的SAM。即a-a-b的父亲变为了a-b。但是无关大雅。
从这个可以看出新建立的辅助点是根据某点为模板,并且为这个模板分担了一些线路的点。
模板点控制这这些辅助点。当且仅当这个模板点被删除后,以这个模板点为模板扩展出去的辅助点才会也才能删除。
声明一个bool is_del[]
结构体里加上一个 bool *d 指针
字符串里的每一个结点对应一个域,即d=is_del[x],那么其复制出来的点也共享这个is_del[x]
当这个字符被删除后,也就是说这个域被删除后,所有的点的*d==0 ,全部删除了
删除从最后一个字符(域)开始删除,删除len个字符(域)即可
删除完之后last需要更新到删除后的第一个点
关于询问
node记录下该点的位置,如果这个状态是后缀,则ans=seq_cnt-i+1
否则为ans=p->pos-i+1
操作1:在原串后面,添加一个串
操作2:查询长度为len的子串或者长度小于等于len的后缀中字典序最小的
操作3:删除最后的len个字符
关于删除
首先明确一点: 新建的点只与模板点有关系
由新加入的点7产生的点8是根据点3为模板进行复制的(复制所有信息,包括位置)。那么点8是有点3控制的。
可以从两个图看出,删除点7,不删除点8也是可以达到第一个图的效果。
只是图不是最简的SAM。即a-a-b的父亲变为了a-b。但是无关大雅。
从这个可以看出新建立的辅助点是根据某点为模板,并且为这个模板分担了一些线路的点。
模板点控制这这些辅助点。当且仅当这个模板点被删除后,以这个模板点为模板扩展出去的辅助点才会也才能删除。
声明一个bool is_del[]
结构体里加上一个 bool *d 指针
字符串里的每一个结点对应一个域,即d=is_del[x],那么其复制出来的点也共享这个is_del[x]
当这个字符被删除后,也就是说这个域被删除后,所有的点的*d==0 ,全部删除了
删除从最后一个字符(域)开始删除,删除len个字符(域)即可
删除完之后last需要更新到删除后的第一个点
关于询问
node记录下该点的位置,如果这个状态是后缀,则ans=seq_cnt-i+1
否则为ans=p->pos-i+1
#include <iostream> #include <cstring> #include <cstdio> #include <string> using namespace std; const int maxn=200005; struct suffixautomaton { struct node { int len,suf;//到这个状态允许的最大长长度,即max(s) node *f,*ch[26]; //如果suf==v_idx,则意味这个状态是后缀子串 bool *d; // int pos; //字符原来的位置 node(){} node(int l) { len=l; f=NULL; memset(ch,0,sizeof(ch)); } }; node *root,*last; node pool[maxn*2]; //储蓄结点用的 node *seq[maxn]; //用于储存输入进来的字符串,,其实就是储存pool数组中主心轴的点。 bool is_del[maxn*2]; //实际上is_del[i] 是代表第i个字符被删除没。node里的 *d是某一个is_del的地址,同一个域里的点共享一个is_del,同在一个域里面的点共享一个is_del[x]. int del_cnt,seq_cnt; //is_del数组的大小,seq数组的大小 int cnt; //结点的数量 int v_idx; //此处的v_idx方便设置suf,避免出错 void init() { v_idx=0; memset(is_del,0,sizeof(is_del)); del_cnt=seq_cnt=0; root=last=pool; seq[0]=root; //此处必须先设置第0位root,避免数组越界 memset(root,0,sizeof(node)); cnt=1; } node * new_node(int l=0) { node *x=pool+cnt++; memset(x,0,sizeof(node)); if(l!=0) x->len=l; return x; } void add(char ch) { int c=ch-'a'; node *p=last,*np=new_node(last->len+1); np->pos=np->len; np->d=is_del+del_cnt++; *np->d=0; seq[seq_cnt=np->len]=np; //以上四行初始化 last=np; for(;NULL!=p&&(NULL==p->ch[c]||*p->ch[c]->d);p=p->f) //如果这个点没有被删除且无下一个点ch p->ch[c]=np; if(NULL==p) np->f=root; else { if(p->ch[c]->len==p->len+1) np->f=p->ch[c]; else { //新建立的点是以p->ch[c]为模板复制的点,共享一个is_del[],当且仅当模板点被删除后新建立的点才会被删除。 node *q=p->ch[c],*nq=new_node(); *nq=*q; nq->len=p->len+1; q->f=np->f=nq; for(;NULL!=p&&p->ch[c]==q;p=p->f) p->ch[c]=nq; } } } void get_suf()//如果suf==v_idx,则意味这个状态是后缀子串 { v_idx++; node *p=last; while(p!=NULL) p->suf=v_idx,p=p->f; root->suf=0; } void del(int len) //从最后一个域开始删除 { while(len--) *seq[seq_cnt--]->d=1; last=seq[seq_cnt]; //last需要改变 } void query(int l) { get_suf(); node *p=root; for(int i=1;i<=l;i++) { for(int j=0;j<26;j++) if(!(NULL==p->ch[j]||*p->ch[j]->d)) { p=p->ch[j]; if(i==l) cout<<p->pos-i+1<<endl; else if(p->suf==v_idx) { cout<<seq_cnt-i+1<<endl; return ; } break; } } } }; suffixautomaton sam; char str[maxn]; int main() { while(scanf("%s",str)!=EOF) { sam.init(); for(int i=0;str[i];i++) sam.add(str[i]); int q,cas,len; scanf("%d",&q); while(q--) { scanf("%d",&cas); if(cas==1) { scanf("%s",str); for(int i=0;str[i];i++) sam.add(str[i]); } else if(cas==2) { scanf("%d",&len); sam.query(len); } else { scanf("%d",&len); sam.del(len); } } } return 0; }
相关文章推荐
- HDU 4622 Reincarnation(SAM 后缀自动机 求子串的不同子串个数)
- HDU 4436 str2int (后缀自动机SAM,多串建立)
- HDU 4436 str2int (后缀自动机SAM,多串建立)
- hdu 4416 Good Article Good sentence (后缀自动机 SAM)
- HDU 3518 Boring counting(后缀自动机 SAM)
- HDU 4270 Dynamic Lover 后缀自动机
- hdu 6208 The Dominator of Strings 后缀自动机 LCS
- HDU 5343 MZL's Circle Zhou(后缀自动机+记忆化搜索)
- hdu 4622 后缀数组计数问题||后缀自动机
- HDU 5442 后缀自动机+kmp
- 2017沈阳网络赛 1001 HDU 6194 string string string(后缀自动机 出现k次的子串个数)
- HDU 4622 Reincarnation (查询一段字符串的不同子串个数,后缀自动机)
- hdu 6208 The Dominator of Strings 后缀自动机 LCS
- Cyclical Quest CodeForces - 235C (后缀自动机 SAM)
- HDU 4622(后缀自动机)
- HDU 5558 Alice's Classified Message(后缀自动机)
- HDU 4622 (后缀自动机)
- SAM后缀自动机学习小记 Poj 1509 Glass Beads (字符串最小表示)
- [后缀自动机 模板题 || 字符串Hash] HDU 4622 Reincarnation
- codeforces 127D Password (后缀自动机 SAM)