[caioj1469][后缀数组]连续重复子串

来源:互联网 发布:sql注入攻击登录 编辑:程序博客网 时间:2024/06/06 02:22

问题描述

求两个字符串的最长公共子串。(长度不超过100000)

样例输入

yeshowmuchiloveyoumydearmotherreallyicannotbelieveit
Yeaphowmuchiloveyoumydearmother

样例输出

27

题解

咳咳首先掩饰一发蒟蒻妄图使用KMP&FFT来D本题的尴尬
然后马上发现kmp和FFT的定义都不是酱的。。
考虑后缀数组
将两个串接起来,跑一遍后缀数组。然后比较height值就ok了
这么简单什么鬼
当个模板用吧

#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>using namespace std;int a[210000],Rsort[210000],Rank[210000],sa1[210000],sa2[210000];int tt[210000];char s[110000];void get_sa(int len,int m){    memcpy(Rank,a,sizeof(Rank));    memset(Rsort,0,sizeof(Rsort));    for(int i=1;i<=len;i++)Rsort[Rank[i]]++;    for(int i=1;i<=m;i++)Rsort[i]+=Rsort[i-1];    for(int i=len;i>=1;i--)sa1[Rsort[Rank[i]]--]=i;    int ln=1,p=0;    while(p<len)    {        int k=0;        for(int i=len-ln+1;i<=len;i++)sa2[++k]=i;        for(int i=1;i<=len;i++)if(sa1[i]-ln>0)sa2[++k]=sa1[i]-ln;        memset(Rsort,0,sizeof(Rsort));        for(int i=1;i<=len;i++)Rsort[Rank[i]]++;        for(int i=1;i<=m;i++)Rsort[i]+=Rsort[i-1];        for(int i=len;i>=1;i--)sa1[Rsort[Rank[sa2[i]]]--]=sa2[i];        memcpy(tt,Rank,sizeof(tt));        Rank[sa1[1]]=1;p=1;        for(int i=2;i<=len;i++)        {            if(tt[sa1[i]]!=tt[sa1[i-1]] || tt[sa1[i]+ln]!=tt[sa1[i-1]+ln])p++;            Rank[sa1[i]]=p;        }        ln*=2;m=p;    }}int height[210000];void get_he(int len){    int j,k=0;    for(int i=2;i<=len;i++)    {        j=sa1[Rank[i]-1];        if(k!=0)k--;        while(a[i+k]==a[j+k])k++;        height[Rank[i]]=k;    }}int main(){    int maxn=0;    scanf("%s",s+1);    int lenx=strlen(s+1);    for(int i=1;i<=lenx;i++){a[i]=s[i]-'A'+1;maxn=max(maxn,a[i]);}    a[lenx+1]=1;    scanf("%s",s+1);    int leny=strlen(s+1);    for(int i=1;i<=leny;i++){a[i+lenx+1]=s[i]-'A'+1;maxn=max(maxn,a[i]);}    int len=lenx+leny+1;    get_sa(len,maxn);    get_he(len);    int ans=0;    for(int i=2;i<=len;i++)    {        if((sa1[i-1]>lenx+1&&sa1[i]<=lenx) || (sa1[i-1]<=lenx&&sa1[i]>lenx+1))ans=max(ans,height[i]);    }    printf("%d\n",ans);    return 0;}
阅读全文
0 0