SPOJ LCS Longest Common Substring

A string is finite sequence of characters over a non-empty finite set Σ.
In this problem, Σ is the set of lowercase letters.
Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.
Now your task is simple, for two given strings, find the length of the longest common substring of them.
Here common substring means a substring of two or more strings.

Input

The input contains exactly two lines, each line consists of no more than 250000 lowercase letters, representing a string.

Output

The length of the longest common substring. If such string doesn’t exist, print “0” instead.

Example

Input:

alsdfkjfjkdsal
fdjskalajfkdsla

Output:

3

Notice:

new testcases added

思路

这里写图片描述
这里写图片描述

代码

#include <cstdio>
#include <cstring>

const int maxn=250000;

struct node
{
  node* tr[26];
  node* par;
  int maxl;

  node(int l=0)
  {
    memset(tr,0,sizeof tr);
    par=NULL;
    maxl=l;
  }
};

struct suffix_automaton
{
  node* qs;
  node* qlast;
  node* qn[maxn+10];
  int l[maxn+10];

  inline int clear()
  {
    delete qs;
    delete qlast;
    qlast=qs=new node();
    return 0;
  }

  inline int addchr(int ch)
  {
    node* p=qlast;
    node* np=new node(qlast->maxl+1);
    qlast=np;
    while((p!=NULL)&&(p->tr[ch]==NULL))
      {
        p->tr[ch]=np;
        p=p->par;
      }
    if(p==NULL)
      {
        np->par=qs;
        return 0;
      }
    node* q=p->tr[ch];
    if(q->maxl!=p->maxl+1)
      {
        node* nq=new node(p->maxl+1);
        memcpy(nq->tr,q->tr,sizeof q->tr);
        nq->par=q->par;
        q->par=np->par=nq;
        while((p!=NULL)&&(p->tr[ch]==q))
          {
            p->tr[ch]=nq;
            p=p->par;
          }
      }
    else
      {
        np->par=q;
      }
    return 0;
  }

  inline int run(char* s,int len)
  {
    qn[0]=qs;
    l[0]=0;
    for(register int i=1; i<=len; ++i)
      {
        node* nq=qn[i-1];
        if(nq->tr[s[i]-'a']!=NULL)
          {
            l[i]=l[i-1]+1;
            qn[i]=nq->tr[s[i]-'a'];
            continue;
          }
        while((nq!=NULL)&&(nq->tr[s[i]-'a']==NULL))
          {
            nq=nq->par;
          }
        if(nq==NULL)
          {
            qn[i]=qs;
            l[i]=0;
            continue;
          }
        qn[i]=nq->tr[s[i]-'a'];
        l[i]=nq->maxl+1;
      }
    int ans=0;
    for(register int i=1; i<=len; ++i)
      {
        if(l[i]>ans)
          {
            ans=l[i];
          }
      }
    return ans;
  }
};

suffix_automaton sam;
int la,lb,l[maxn+10];
char a[maxn+10],b[maxn+10];

int main()
{
  scanf("%s%s",a+1,b+1);
  la=strlen(a+1);
  lb=strlen(b+1);
  sam.clear();
  for(register int i=1; i<=lb; ++i)
    {
      sam.addchr(b[i]-'a');
    }
  printf("%d\n",sam.run(a,la));
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值