A - Longest Common Substring SPOJ - LCS

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

题解:这里是一个子串匹配的问题
首先我们把第一个串建SAM,然后用第二个串进行去匹配。设当前长度为len,如果匹配就继续往下,len++。如果不匹配了就要跳fa,直到跳到有这个出边了即可。有两种情况。
第一种情况:跳到根了,我们要重置len。继续匹配下去。
第二种情况:那我们就沿p的fa不断走直到发现有c这个转移位置,len变为len[p]+1(相当于我知道B串的某一部分已经在A串中匹配,现在下一位无法匹配,我就不断取B串的后缀直到发现下一位可以匹配)。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct node
{
  int len,fa;
  int ch[26];
  node(){memset(ch,0,sizeof(ch));len=0;}
}dian[N<<1];
string s,s1;
int las=1,tot=1;
void add(int c)
{
  int p=las;
  int np=las=++tot;
  dian[np].len=dian[p].len+1;
  for(;p&&!dian[p].ch[c];p=dian[p].fa) dian[p].ch[c]=np;
  if(!p) dian[np].fa=1;
  else
  {
    int q=dian[p].ch[c];
    if(dian[q].len==dian[p].len+1) dian[np].fa=q;
    else
    {
      int nq=++tot;
      dian[nq]=dian[q];
      dian[nq].len=dian[p].len+1;
      dian[q].fa=dian[np].fa=nq;
      for(;p&&dian[p].ch[c]==q;p=dian[p].fa) dian[p].ch[c]=nq;
    }
  }
}
int main()
{
  cin>>s>>s1;
  for(int i=0;i<s.size();i++) add(s[i]-'a');
  int len=0;
  int p=1;
  int res=0;
  for(int i=0;i<s1.size();i++)
  {
    int c=s1[i]-'a';
    if(dian[p].ch[c]) {len++;p=dian[p].ch[c];} //如果匹配成功,那就继续往下匹配,len++
    else
    {
        for(;p&&!dian[p].ch[c];p=dian[p].fa);//发生了失配,我们我要跳fa,跳到我们之前匹配好的后缀上
        if(!p) p=1,len=0;//如果跳到根了,那么就要重新来了
        //相当于我知道B串的某一部分已经在A串中匹配,现在下一位无法匹配,我就不断取B串的后缀直到发现下一位可以匹配
        else len=dian[p].len+1,p=dian[p].ch[c]; //如果跳到了之前已经有后缀的上面,那么长度自然等于当前节点的长度+1
      }
      res=max(res,len);
    }
    printf("%d\n",res);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值