POJ 2217 (後綴數組+LCP)

要注意最後的空串也要算進去,所以是<=n


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <set>
#include <vector>
#include <cmath>
#define LL long long
#define eps 1e-8
const LL INF = 0x3f3f3f3f;
const int maxn = 200000 + 5;
using namespace std;
int sa[maxn*2];
int t[maxn*2];
int t2[maxn*2];
int c[maxn*2];
int Rank[maxn];
int lcp[maxn];
string s1, s2;
void get_lcp(int n, string s){
    int i,j,k = 0;
    for(i=0; i<=n; i++) Rank[sa[i]] = i;
    for(i=0; i<n; i++){
        if(k) k--;
        j = sa[Rank[i]-1];
        while(s[i+k] == s[j+k]) k++;
        lcp[Rank[i]-1] = k;
    }
}
void build_sa(int n, int m, string s){
    int *x = t, *y = t2;
    n++;
    for(int i=0; i<m; i++) c[i] = 0;
    for(int i=0; i<n; i++) c[x[i] = s[i]]++;
    for(int i=1; i<m; i++) c[i] += c[i-1];
    for(int i=n-1; i>=0; i--) sa[--c[x[i]]] = i;
    for(int k=1; k<=n; k<<=1){
        int p = 0;
        for(int i=n-k; i<n; i++) y[p++] = i;
        for(int i=0; i<n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
        for(int i=0; i<m; i++) c[i] = 0;
        for(int i=0; i<n; i++) c[x[y[i]]]++;
        for(int i=0; i<m; i++) c[i] += c[i-1];
        for(int i=n-1; i>=0; i--) sa[--c[x[y[i]]]] = y[i];
        swap(x,y);
        p = 1; x[sa[0]] = 0;
        for(int i=1; i<n; i++)
            x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++;
        if(p >= n) break;
        m = p;
    }
}
int main(){
    int T;
    scanf("%d",&T);
    getchar();
    while(T--){
        getline(cin,s1);
        getline(cin,s2);
        int len = (int)s1.length();
        s1 += '#' + s2;
        int n = (int)s1.length();
        build_sa(n,300,s1);
        get_lcp(n,s1);
        int ans = 0;
        for(int i=0; i<n; i++){
            if((sa[i] < len) != (sa[i+1] < len)){
                ans = max(ans, lcp[i]);
            }
        }
        printf("Nejdelsi spolecny retezec ma delku %d.\n",ans);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章