【后缀自动机】[SPOJLCS]Longest Common Substring

题目大意

给两个长度小于100000的字符串A和B,求出他们的最长公共连续子串。

分析

后缀自动机基础题。
根据A串构造后缀自动机,然后用B串进行匹配。假设前匹配到了s[i],l为上次停留的节点,如果l有儿子s[i],len++,l=l->ch[s[i]],否则,沿着失配边走到当前第一个有儿子s[i]的节点a,len=a节点所表示的最大的字串长度+1,l=a->ch[s[i]];
ans即为过程中匹配到的最长的字串。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 250000
#define MAXC 26
using namespace std;
char s[MAXN+10];
int n,ans;
struct node{
    int len;
    node *ch[MAXC],*fail;
}tree[MAXN*2+10],*tcnt=tree,*root=tcnt,*l=root;
void insert(char c){
    c-='a';
    node *p=l,*np=++tcnt,*q,*nq;
    np->len=p->len+1;
    l=np;
    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);
    n=strlen(s);
    int i;
    for(i=0;i<n;i++)
        insert(s[i]);
    scanf("%s",s);
    n=strlen(s);
}
void solve(){
    int i,len=0;
    node *p=root;
    for(i=0;i<n;i++){
        s[i]-='a';
        if(p->ch[s[i]])
            p=p->ch[s[i]],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]];
        }
        ans=max(ans,len);
    }
}
int main()
{
    read();
    solve();
    printf("%d\n",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值