• SP1812 LCS2


    SP1812 LCS2 - Longest Common Substring II

    题意

    给出一些字符串,求出他们的最长公共子串。

    分析

    对其中一个字符串建后缀自动机,用其他字符串在自动机上跑,用一个数组对每个状态记录一个能匹配的最长的长度,最后对所有字符串跑自动机后维护的匹配的最长长度取min,再对所有状态取max,即为答案。

    Code

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<iomanip>
    #include<sstream>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<bitset>
    #include<queue>
    #include<cmath>
    #include<stack>
    #include<set>
    #include<map>
    #define rep(i,x,n) for(int i=x;i<=n;i++)
    #define per(i,n,x) for(int i=n;i>=x;i--)
    #define sz(a) int(a.size())
    #define rson mid+1,r,p<<1|1
    #define pii pair<int,int>
    #define lson l,mid,p<<1
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define se second
    #define fi first
    using namespace std;
    const double eps=1e-8;
    const int mod=1e9+7;
    const int N=2e6+10;
    const int inf=1e9;
    int n;
    char s[N];
    struct SAM{
        int last,cnt;int ch[N][26],fa[N],len[N],sum[N],id[N],mx[N],g[N];
        int newnode(){
            ++cnt;
            return cnt;
        }
        void insert(int c){
            int p=last,np=newnode();last=np;len[np]=len[p]+1;
            for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
            if(!p) fa[np]=1;
            else {
                int q=ch[p][c];
                if(len[q]==len[p]+1) fa[np]=q;
                else{
                    int nq=newnode();
                    len[nq]=len[p]+1;
                    memcpy(ch[nq],ch[q],sizeof ch[q]);
                    fa[nq]=fa[q],fa[q]=fa[np]=nq;
                    for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
                }
            }
        }
        void init(){
            last=cnt=1;
        }
        void gao(){
            rep(i,1,cnt) sum[len[i]]++;
            rep(i,1,cnt) sum[i]+=sum[i-1];
            rep(i,1,cnt) id[sum[len[i]]--]=i;
            rep(i,1,cnt) g[i]=len[i];
        }
        void cal(){
            rep(i,1,cnt) mx[i]=0;
            int u=1,l=0;
            rep(i,1,n){
                int c=s[i]-'a';
                while(!ch[u][c]&&u!=1) u=fa[u],l=len[u];
                if(ch[u][c]) u=ch[u][c],l++;
                mx[u]=max(mx[u],l);
            }
            per(i,cnt,1) mx[fa[id[i]]]=max(mx[fa[id[i]]],mx[id[i]]);
            rep(i,1,cnt) g[i]=min(g[i],mx[i]);
        }
        int solve(){
            int ans=0;
            rep(i,1,cnt) ans=max(ans,g[i]);
            return ans;
        }
    }sam;
    int main(){
        scanf("%s",s+1);
        sam.init();
        n=strlen(s+1);
        rep(i,1,n) sam.insert(s[i]-'a');
        sam.gao();
        while(~scanf("%s",s+1)){
            n=strlen(s+1);
            sam.cal();
        }
        printf("%d
    ",sam.solve());
        return 0;
    }
    
  • 相关阅读:
    IoC之Ninject
    C#中的扩展方法
    Office 2016 Pro Plus Project 专业版 Visio 专业版 64 位vol版本方便KMS小马oem
    Microsoft Office 2016 简体中文 Vol 版镜像下载
    svn 被锁住 冲突 Can't revert without reverting children
    定时检查服务批处理,发现服务停止立即启动服务
    C++中关于[]静态数组和new分配的动态数组的区别分析
    IP地址与无符号整数值相互转换
    算法:整数与ip地址转换
    将字符串表示的IP地址转变为整形表示
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13938553.html
Copyright © 2020-2023  润新知