zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    个人作业3——个人总结(Alpha阶段)
    单元测试
    个人作业2——英语学习APP案例分析
    结对作业-基于GUI的四则运算
    个人作业1:小学四则运算——基于控制台
    个人作业3--------个人总结(Alpha版本)
    结对作业 2
    个人作业 2
    结对作业 肖荣森(201421123079) 苏上鑫(201421123081)
    作业1---四则运算
  • 原文地址:https://www.cnblogs.com/acmLLF/p/13646451.html
Copyright © 2011-2022 走看看