SPOJ1811 最长公共子串

如题

N<=250000

倍增后缀数组和DC3都过不了  ,据说有的人DC3能过

后缀自动机

首先对A串建立后缀自动机

然后让B在A上匹配

考虑B的逐位匹配,维护一个cur节点,一开始这个节点是空节点,也就是1

然后如果cur的转移里面有B[i] ,那么ans++,  cur转移到下个节点

如果匹配不到,那么往他的fa去走,判断是否有转移,如果有转移就更新一下

然后维护最大答案就可以了

#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,a,n) for(int i=n;i>=a;--i)
#define pb push_back
#define fi first
#define se second
#define io std::ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, INF = 0x3f3f3f3f;

ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
ll qpow(ll a,ll n)
{
    ll r=1%P;
    for (a%=P; n; a=a*a%P,n>>=1)if(n&1)r=r*a%P;
    return r;
}
const int maxn=2e6;

struct Suffix_Automata {
  int maxlen[maxn], trans[maxn][26], link[maxn], Size, Last;
  int siz[maxn];
  int t[maxn],A[maxn];
  Suffix_Automata() { Size = Last = 1; }
  inline void Extend(int id) {
    int cur = (++ Size), p;
    siz[Size]=1;
    maxlen[cur] = maxlen[Last] + 1;
    for (p = Last; p && !trans[p][id]; p = link[p]) trans[p][id] = cur;
    if (!p) link[cur] = 1;
    else {
      int q = trans[p][id];
      if (maxlen[q] == maxlen[p] + 1) link[cur] = q;
      else {
        int clone = (++ Size);
        maxlen[clone] = maxlen[p] + 1;
        memcpy(trans[clone], trans[q],sizeof(trans[q]));
        link[clone] = link[q];
        for (; p && trans[p][id] == q; p = link[p]) trans[p][id] = clone;
        link[cur] = link[q] = clone;
      }
    }
    Last = cur;
  }
  void buildtree()
  {
      for(int i=1;i<=Size;i++) t[maxlen[i]]++;
      for(int i=1;i<=Size;i++) t[i]+=t[i-1];
      for(int i=1;i<=Size;i++) A[t[maxlen[i]]--]=i;
  }
} T;
char s[250005];
char a[250005];
int main()
{
     cin>>s+1;
     int n=strlen(s+1);
     for(int i=1;i<=n;i++)
     {
       T.Extend(s[i]-'a');
     }
     cin>>a+1;
     int ans=0;
     int len=strlen(a+1);
     int cur=1;
     int _max=0;
     for(int i=1;i<=len;i++)
     {   int now=a[i]-'a';
         if(T.trans[cur][now])
         {
            ans++;
            cur=T.trans[cur][now];
         }
         else
         {
             while(!T.trans[cur][now]&&cur!=1)
                cur=T.link[cur];
             if(T.trans[cur][now])
             {

                 ans=T.maxlen[cur]+1;
                 cur=T.trans[cur][now];
             }
             else
                ans=0;
         }
         _max=max(_max,ans);
     }
     cout<<_max<<endl;
}

 

posted @ 2020-09-10 16:20  摸鱼选手LLF  阅读(119)  评论(0编辑  收藏  举报