【再谈后缀自动机(入门)】[SPOJLCS2]Longest Common Substring II
来源:互联网 发布:mac 命令行 删除软件 编辑:程序博客网 时间:2024/05/19 23:54
题目大意
给出
分析
关于后缀自动机
复习过程中再看后缀自动机,把许多初学的时候没弄懂的问题解决了。
首先要明确后缀自动机的每个节点所表示的是一个终点等价类,从根节点走到叶子节点就对应一个后缀,
后缀边所指向的节点所对应的终点等价类的终点包含当前节点的终点等价类对应的终点。
在构建的过程中
q−>len≠p−>len+1 ,说明由p 转移到q 并不是q 点所对应的最长的字符串但这却是能够增加这个终点的最长的字符串,q 所对应的长于该长度的字符串都不能增加这个终点,,所以我们新建一个节点nq ,将q 的信息复制给他(len,fail,ch) ,nq→len=p→len+1,q→fial=nq,np→fial=nq ,并且沿着后缀边走,将所有有字符c 转移且转移到q 的转移重定向至nq 。
为什么ch 也要复制?
因为这个节点对应的字符串加上转移的边所对应的字符形成的字符串的终点和这个节点的终点的没有关系,所以要保证这个节点的儿子节点所对应的字符串不变。q−>len=p−>len+1 ,则np→fial=q
这道题
每个节点保存两个值:当前字符串能够匹配这个节点对应的字符串的最大长度
然后,每次匹配完之后要沿着后缀边更新
代码
#include<cstdio>#include<cstring>#include<algorithm>#define INF 0x7fffffff#define MAXN 100000using namespace std;void Read(int &x){ char c; while(c=getchar(),c!=EOF) if(c>='0'&&c<='9'){ x=c-'0'; while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0'; ungetc(c,stdin); return; }}struct node{ int len,mx,nmx; node *ch[26],*fail;}tree[MAXN*2+10],*tcnt=tree,*root=tcnt,*l=tcnt,*r[MAXN*2+10];char s[MAXN+10];int ans,b[MAXN+10];void insert(char c){ c-='a'; node *p=l,*np=++tcnt,*q,*nq; l=np; np->len=p->len+1; while(p&&!p->ch[c]) p->ch[c]=np,p=p->fail; if(!p) np->fail=root; else{ q=p->ch[c]; if(q->len==p->len+1) np->fail=q; else{ nq=++tcnt; *nq=*q; nq->len=p->len+1; q->fail=nq; np->fail=nq; while(p&&p->ch[c]==q) p->ch[c]=nq,p=p->fail; } }}void read(){ scanf("%s",s); for(int i=0;s[i];i++) insert(s[i]);}void solve(){ int i,len,tot; node *p; for(p=tree;p<=tcnt;p++){ p->mx=p->len,p->nmx=0; b[p->len]++; } for(i=1;s[i-1];i++) b[i]+=b[i-1]; for(p=tree;p<=tcnt;p++) r[--b[p->len]]=p; tot=tcnt-tree; while(~scanf("%s",s)){ p=root; len=0; for(i=0;s[i];i++){ s[i]-='a'; if(p->ch[s[i]]){ p=p->ch[s[i]]; p->nmx=max(p->nmx,++len); } else{ while(p&&!p->ch[s[i]]) p=p->fail; if(!p) p=root,len=0; else{ len=p->len+1; p=p->ch[s[i]]; p->nmx=max(p->nmx,len); } } } for(i=tot;i;i--){ r[i]->fail->nmx=max(r[i]->nmx,r[i]->fail->nmx);//不用和r[i]->len进行比较,因为不会影响更新r[i]->mx r[i]->mx=min(r[i]->mx,r[i]->nmx); r[i]->nmx=0; } } for(p=tree;p<=tcnt;p++) ans=max(ans,p->mx);}int main(){ read(); solve(); printf("%d\n",ans);}
0 0
- 【再谈后缀自动机(入门)】[SPOJLCS2]Longest Common Substring II
- [spoj1812]Longest Common Substring II && 后缀自动机
- 【spoj1812】Longest Common Substring II 后缀自动机
- SPOJ1812 Longest Common Substring II 后缀自动机
- SPOJ 1812. Longest Common Substring II(后缀自动机)
- spoj1812 Longest Common Substring II(LCS2),后缀自动机
- SPOJ LCS2 Longest Common Substring II 后缀自动机
- 【后缀自动机】[SPOJ LCS2]Longest Common Substring II
- spoj 1812 LCS2 - Longest Common Substring II (后缀自动机)
- SPOJ lcs2 Longest Common Substring II 后缀自动机
- spoj 1812 Longest Common Substring II(后缀自动机)
- SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机)
- [SPOJ1812]LCS2 - Longest Common Substring II(后缀自动机)
- BZOJ2946 SPOJ1812:Longest Common Substring II(后缀自动机)
- 【后缀自动机】SPOJ(LCS2)[Longest Common Substring II]题解
- SPOJ Longest Common Substring II 后缀自动机(打印)
- spoj 1811 Longest Common Substring (后缀自动机)
- SPOJ LCS Longest Common Substring 后缀自动机
- nginx负载均衡配置
- iOS UIDevice- NSBundle - NSlocale
- 111-e-Minimum Depth of Binary Tree
- bzoj 3876(有上下界的最小费用流)
- 游戏人物 退出江湖
- 【再谈后缀自动机(入门)】[SPOJLCS2]Longest Common Substring II
- h264 NAL头解析
- 进程调度
- 喷水装置(一)t贪心算法
- 20160406servlet学习笔记验证码
- LeetCode 12 Integer to Roman
- NOJ-2076-天神小学-典型BFS题型
- uvaoj384最优矩阵链乘(详解 + 思考 + 记忆化搜索 + 递推 )
- Quick_触摸事件