POJ 2217 (最长公共子串)

先考虑一个简单的问题,计算一个字符串中至少出现两次以上的最长子串,答案一定会在后缀数组中相邻两个后缀的公共前缀之中,所有只要考虑他们就好了,原因是子串的开始位置在后缀中相距越远,其公共前缀的长度也就越短,因此,高度数组的最大值就是答案。

再考虑这个问题的解法,因为对于两个字符串,不好直接运用后缀数组,所以我i们可以在S,T中间插入一个不会出现的字符('\0')拼成一个字符串  S''  ,然后,计算  S‘’   的后缀数组,检查后缀数组的所有相邻后缀,其中,分属于S和T的不同字符串的后缀的lcp的最大值就是答案。而要知道后缀时属于S还是T,可以由其在  S''  中的位置直接判断。

#include<cstdio>
#include<algorithm>
#include<string>
#include<iostream>
#include<cstring>

using namespace std;

const int maxn=1e4+10;

int rankk[maxn];
int tmp[maxn];
int k,n;
string s,t;
int sa[maxn],lcp[maxn];

bool compare_sa(int i,int j){
    if(rankk[i]!=rankk[j]){
        return rankk[i]<rankk[j];
    }else{
        int ri=i+k<=n?rankk[i+k]:-1;
        int rj=j+k<=n?rankk[j+k]:-1;
        return ri<rj;
    }
}

void construct_sa(string s,int *sa){
    for(int i=0;i<=n;i++){
        sa[i]=i;
        rankk[i]=i<n?s[i]:-1;
    }
    for(k=1;k<=n;k<<=1){
        sort(sa,sa+n+1,compare_sa);
        tmp[sa[0]]=0;
        for(int i=1;i<=n;i++){
            tmp[sa[i]]=tmp[sa[i-1]]+(compare_sa(sa[i-1],sa[i])?1:0);
        }
        for(int i=0;i<=n;i++){
            rankk[i]=tmp[i];
        }
    }
}

void construct_lcp(string s,int *sa,int *lcp){
    int n=s.size();
    for(int i=0;i<=n;i++){
        rankk[sa[i]]=i;
    }
    int h=0;
    lcp[0]=0;
    for(int i=0;i<n;i++){
        int j=sa[rankk[i]-1];
        if(h) h--;
        for(;j+h<n&&i+h<n;h++){
            if(s[j+h]!=s[i+h]) break;
        }
        lcp[rankk[i]-1]=h;
    }
}

void solve(){
    int s1=s.size();
    s=s+'\0'+t;
    construct_sa(s,sa);
    construct_lcp(s,sa,lcp);
    int ans=0;
    for(int i=0;i<n;i++){
        if((sa[i]<s1)!=(sa[i+1]<s1)){
            ans=max(ans,lcp[i]);
        }
    }
    cout<<"Nejdelsi spolecny retezec ma delku "<<ans<<"."<<endl;
}

int main(){
    ios::sync_with_stdio(0);
    int cs;
    cin>>cs;
    cin.ignore();
    while(cs--){
        getline(cin,s);
        getline(cin,t);
        n=s.size()+t.size()+1;
        solve();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40679299/article/details/82151156