【后缀自动机】SPOJ(LCS)[Longest Common Substring]题解
来源:互联网 发布:高级sql生成选项 编辑:程序博客网 时间:2024/05/22 03:22
题目概述
给出两个串A和B,求A和B的最长公共子串。
解题报告
这道题是SAM的经典应用,首先先提醒一下不要一看到LCS就想到最长公共子序列去了,这里是最长公共字串……
SAM真的是很神的字符串算法啊,不仅复杂度是线性的,还非常好写,但是真的太神了,所以很多可以用SAM的地方还需要各种转化。
我们先对A串建立SAM,那么现在我们就可以识别A的所有子串了。我们按顺序枚举B的前缀i,判断该前缀的后缀是否出现在A中。先记录p表示处理前缀i-1时到达的状态,再记录len表示当前B的前缀能匹配到的后缀的长度。如果p能够沿着B[i]走下去,那么说明B的前缀i能够匹配到的后缀的长度就是len+1(从前面延伸过来),否则p就必须沿着father树向上走,走到能继续扩展为止,如果能扩展,那么len=p->MAX+1,p=p->son[B[i]],否则如果最终并不能扩展,就说明p=root,len=0。
示例程序
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxl=250000,maxi=26;char A[maxl+5],B[maxl+5];struct SAM{ struct node { node *son[maxi],*fa;int MAX; node(int M) {MAX=M;fa=0;memset(son,0,sizeof(son));} }; typedef node* P_node; P_node ro,lst; SAM() {ro=new node(0);lst=ro;} void Insert(char ch) { int ID=ch-'a';P_node p=lst,np=new node(lst->MAX+1); while (p&&!p->son[ID]) p->son[ID]=np,p=p->fa; if (!p) np->fa=ro; else { P_node q=p->son[ID]; if (p->MAX+1==q->MAX) np->fa=q; else { P_node nq=new node(p->MAX+1); memcpy(nq->son,q->son,sizeof(q->son)); nq->fa=q->fa;q->fa=nq;np->fa=nq; while (p&&p->son[ID]==q) p->son[ID]=nq,p=p->fa; } } lst=np; } void make_SAM(char *s) {for (int i=1;s[i];i++) Insert(s[i]);} int LCS(char *s) //求此后缀自动机对应字符串与s的LCS { int ans=0,len=0;P_node p=ro; for (int i=1;s[i];i++) { int ID=s[i]-'a'; if (p->son[ID]) p=p->son[ID],len++; else { while (p&&!p->son[ID]) p=p->fa; if (!p) p=ro,len=0; else len=p->MAX+1,p=p->son[ID]; } ans=max(ans,len); //从所有len中刷出最优解 } return ans; }};SAM sam;char readc(){ static char buf[100000],*l=buf,*r=buf; if (l==r) r=(l=buf)+fread(buf,1,10000,stdin); if (l==r) return EOF; else return *l++;}int reads(char *s){ int len=0;char ch=readc();if (ch==EOF) return EOF; while ('z'<ch||ch<'a') ch=readc();s[++len]=ch; while ('a'<=s[len]&&s[len]<='z') s[++len]=readc();s[len--]=0; return len;}int main(){ freopen("program.in","r",stdin); freopen("program.out","w",stdout); reads(A);reads(B);sam.make_SAM(A); printf("%d\n",sam.LCS(B)); return 0;}
阅读全文
0 0
- 【后缀自动机】SPOJ(LCS)[Longest Common Substring]题解
- SPOJ LCS Longest Common Substring 后缀自动机
- [SPOJ LCS]Longest Common Substring && 后缀自动机
- 【后缀自动机】[SPOJ LCS]Longest Common Substring
- spoj 1811 LCS - Longest Common Substring (后缀自动机)
- 【后缀自动机】SPOJ(LCS2)[Longest Common Substring II]题解
- 后缀数组 spoj LCS - Longest Common Substring
- spoj 1811 Longest Common Substring (后缀自动机)
- SPOJ-1811 Longest Common Substring(后缀自动机)
- SPOJ LCS(Longest Common Substring-后缀自动机-结点的Parent包含关系)
- SPOJ 题目1811 LCS - Longest Common Substring(后缀自动机求最长公共子串)
- SPOJ LCS Longest Common Substring
- spoj1811 Longest Common Substring(LCS),后缀自动机
- [SPOJ1811]LCS - Longest Common Substring(后缀自动机)
- SPOJ 1811 Longest Common Substring(后缀自动机)
- SPOJ 1812. Longest Common Substring II(后缀自动机)
- spoj 1811 Longest Common Substring (第一道后缀自动机)
- SPOJ LCS2 Longest Common Substring II 后缀自动机
- JAVA设计模式之抽象工厂模式
- Android微信支付开发流程
- java发起http请求获取返回的Json对象
- 在子窗体退出后,父窗体出现登录页面的混乱
- JavaScript05—自定义对象、事件、计算器
- 【后缀自动机】SPOJ(LCS)[Longest Common Substring]题解
- 纯粹经济学 —— 基本概念
- 算法概论第八章 NP完全问题 习题证明
- 【WinterCamp 2013】数三角形
- anaconda2和anaconda3共存情况下安装opencv3库的方法
- spark mllib源码分析之L-BFGS(一)
- ubuntu添加开机启动项的方法
- 可爱的NPM 淘宝镜像
- 3173: [Tjoi2013]最长上升子序列