spoj 1811 LCS (后缀自动机 SAM)
2013-03-25 21:20
363 查看
http://www.spoj.com/problems/LCS/
题意:求两个字符串A,B的最长公共子串。字符串长度不超过250000。
思路:这应该算是后缀自动机的经典应用了吧,我们先构造A的SAM,然后用A的SAM一次读入B的每一个字符,初始时状态在root处,此时最大匹配数为tmp=0,(这里的最大匹配数是指以当前读入的字符结尾,往前能匹配的最大长度),设当前到达的状态为p,最大匹配数为tmp,读入的字符为x,若p->go[x]!=NULL,则说明可从当前状态读入一个字符x到达下一个状态,则tmp++,p=p->go[x],否则,找到p的第一个祖先s,s->go[x]!=NULL,若s不存在,则说明以x结尾的字符串无法和A串的任何位置匹配,则设tmp=0,p=root。否则,设tmp=s->tmp+1(因为我们不算x的话已经到达了状态p,这说明对于p的任意祖先已经匹配完毕),p=s->go[x]。我们求tmp所达到的最大值即为所求。代码如下:
题意:求两个字符串A,B的最长公共子串。字符串长度不超过250000。
思路:这应该算是后缀自动机的经典应用了吧,我们先构造A的SAM,然后用A的SAM一次读入B的每一个字符,初始时状态在root处,此时最大匹配数为tmp=0,(这里的最大匹配数是指以当前读入的字符结尾,往前能匹配的最大长度),设当前到达的状态为p,最大匹配数为tmp,读入的字符为x,若p->go[x]!=NULL,则说明可从当前状态读入一个字符x到达下一个状态,则tmp++,p=p->go[x],否则,找到p的第一个祖先s,s->go[x]!=NULL,若s不存在,则说明以x结尾的字符串无法和A串的任何位置匹配,则设tmp=0,p=root。否则,设tmp=s->tmp+1(因为我们不算x的话已经到达了状态p,这说明对于p的任意祖先已经匹配完毕),p=s->go[x]。我们求tmp所达到的最大值即为所求。代码如下:
#include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> #define maxn 500010 using namespace std; char str[maxn>>1]; struct node { node *par,*go[26]; int val; }*root,*tail,que[maxn],*top[maxn]; int tot,len,c[maxn]; void add(int c,int l) { node *np=&que[tot++],*p=tail; np->val=l; while(p&&p->go[c]==NULL) { p->go[c]=np; p=p->par; } if(p==NULL) np->par=root; else { node *q=p->go[c]; if(q->val==p->val+1) np->par=q; else { node *nq=&que[tot++]; *nq=*q; nq->val=p->val+1; np->par=q->par=nq; while(p&&p->go[c]==q) { p->go[c]=nq; p=p->par; } } } tail=np; } void init(int n) { for(int i=0;i<=n;i++) { memset(que[i].go,0,sizeof(que[i].go)); que[i].val=0; } tot=0; len=1; root=tail=&que[tot++]; } void solve() { int i; scanf("%s",str); int l=strlen(str),ans=0,tmp=0; node *p=root; for(i=0;i<l;i++) { int x=str[i]-'a'; if(p->go[x]) { p=p->go[x]; tmp++; } else { while(p&&p->go[x]==NULL) p=p->par; if(p) { tmp=p->val+1; p=p->go[x]; } else { p=root; tmp=0; } } if(tmp>ans) ans=tmp; } printf("%d\n",ans); } int main() { //freopen("dd.txt","r",stdin); scanf("%s",str); int l=strlen(str); init(l*2); for(int i=0;i<l;i++) add(str[i]-'a',len++); solve(); return 0; }
相关文章推荐
- spoj/LCS 1811 小小后缀自动机
- 后缀自动机(SAM) :SPOJ LCS - Longest Common Substring
- SPOJ 1811 LCS [后缀自动机]
- SPOJ 1811(LCS) 后缀自动机
- spoj 1811 LCS - Longest Common Substring (后缀自动机)
- SPOJ 题目1811 LCS - Longest Common Substring(后缀自动机求最长公共子串)
- spoj 1811 LCS 后缀自动机
- SPOJ 1811 LCS 后缀自动机
- [SPOJ1811]LCS - Longest Common Substring(后缀自动机)
- SPOJ 1811. Longest Common Substring (LCS,两个字符串的最长公共子串, 后缀自动机SAM)
- SPOJ 1811. Longest Common Substring (LCS,两个字符串的最长公共子串, 后缀自动机SAM)
- spoj lcs2 后缀自动机SAM
- SPOJ 1811 LCS(后缀自动机)
- SPOJ 1811 LCS,SPOJ 1812 LCS2【SAM裸题,clj的ppt很清楚
- [SPOJ LCS]Longest Common Substring && 后缀自动机
- SPOJ1811 [后缀自动机]
- SPOJ 1811 Longest Common Substring 后缀自动机
- SPOJ 1812 LCS2 后缀自动机
- SPOJ LCS 后缀自动机找最大公共子串
- SPOJ LCS(Longest Common Substring-后缀自动机-结点的Parent包含关系)