Longest Common Substring SPOJ - LCS

题目大意:给你两个字符串,让你找到他们的最长公共子串的长度

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <set>
#include <queue>
using namespace std;
const int maxn = 250000  + 10;
const int CHAR = 28;
struct SAM_Node
{
    SAM_Node *fa,*next[CHAR];
    int len;
    int id,pos;
    SAM_Node(){}
    SAM_Node(int l)
    {
        fa=0;
        len=l;
        memset(next,0,sizeof(next));
    }
} ;
SAM_Node SAM_node[maxn*2],*SAM_rot,*SAM_last;
int SAM_size;
SAM_Node *newSAM_Node(int len)
{
    SAM_node[SAM_size]=SAM_Node(len);
    SAM_node[SAM_size].id=SAM_size;
    return &SAM_node[SAM_size++];
}
SAM_Node *newSAM_Node(SAM_Node *p)
{
    SAM_node[SAM_size]=*p;
    SAM_node[SAM_size].id=SAM_size;
    return &SAM_node[SAM_size++];
}
void SAM_init()
{
    SAM_size=0;
    SAM_rot=SAM_last=newSAM_Node(0);
    SAM_node[0].pos=0;
}
void SAM_add(int x,int len)
{
    SAM_Node *p=SAM_last,*np=newSAM_Node(p->len+1);
    np->pos=len;
    SAM_last=np;
    for(;p&&!p->next[x];p=p->fa)
    {
        p->next[x]=np;
    }
    if(!p)
    {
        np->fa=SAM_rot;
        return ;
    }
    SAM_Node *q = p->next[x];
    if(q->len==p->len+1)
    {
        np->fa=q;
        return ;
    }
    SAM_Node *nq=newSAM_Node(q);
    nq->len=p->len+1;
    q->fa=nq;
    np->fa=nq;
    for(;p&&p->next[x]==q;p=p->fa)
    {
        p->next[x]=nq;
    }
}
char s1[maxn],s2[maxn];
int main()
{
    while(~scanf("%s",s1))
    {
        scanf("%s",s2);
        SAM_init();
        int len1=strlen(s1);
        int len2=strlen(s2);
        for(int i=0;i<len1;i++)
            SAM_add(s1[i]-'a',i+1);
        int ans = 0;
        SAM_Node *p = SAM_rot;
        int num = 0;
        for(int i=0;i<len2;i++)
        {
            int x = s2[i]-'a';
           // cout<<i<<" "<<x<<" "<<endl;
            if(p->next[x])
            {
                num = num + 1;
                p = p->next[x];
              //  cout<<444<<" "<<num<<endl;
            }
            else
            {
               // cout<<i<<" "<<222<<endl;
                while(p&&p->next[x]==0) p = p->fa;
               // cout<<i<<" "<<333<<endl;
                if(!p)
                {
                    num = 0;
                    p = SAM_rot;
                }
                else{
                    num = p->len + 1;
                    p = p->next[x];
                }
            }
            ans = max(ans,num);
        }
        printf("%d\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值