[POJ 2774] Long Long Message

[题目链接]

         http://poj.org/problem?id=2774

[算法]

        后缀数组

        详见2009国家集训队论文集之 : 《后缀数组——处理字符串的有利工具》

        时间复杂度 : O(NlogN)

[代码]

         

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include <cwchar>
#include <cwctype>
#include <stack>
#include <limits.h>
using namespace std;
#define MAXN 500010

int n , t1 , t2;
char A[MAXN] , B[MAXN] , s[MAXN];
int height[MAXN] , sa[MAXN] , rk[MAXN] , x[MAXN] , y[MAXN] , cnt[MAXN];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
inline void build_sa()
{
        memset(cnt , 0 , sizeof(cnt));
        for (int i = 1; i <= n; i++) ++cnt[(int)s[i]];
        for (int i = 1; i <= 256; i++) cnt[i] += cnt[i - 1];
        for (int i = n; i >= 1; i--) sa[cnt[(int)s[i]]--] = i;
        rk[sa[1]] = 1;
        for (int i = 2; i <= n; i++) rk[sa[i]] = rk[sa[i - 1]] + (s[sa[i - 1]] != s[sa[i]]);
        for (int k = 1; rk[sa[n]] != n; k <<= 1)
        {
                for (int i = 1; i <= n; i++)
                        x[i] = rk[i] , y[i] = (i + k <= n) ? rk[i + k] : 0;
                memset(cnt , 0 , sizeof(cnt));
                for (int i = 1; i <= n; i++) ++cnt[y[i]];
                for (int i = 1; i <= n; i++) cnt[i] += cnt[i - 1];
                for (int i = n; i >= 1; i--) rk[cnt[y[i]]--] = i;
                memset(cnt , 0 , sizeof(cnt));
                for (int i = 1; i <= n; i++) ++cnt[x[i]];
                for (int i = 1; i <= n; i++) cnt[i] += cnt[i - 1];
                for (int i = n; i >= 1; i--) sa[cnt[x[rk[i]]]--] = rk[i];
                rk[sa[1]] = 1;
                for (int i = 2; i <= n; i++) rk[sa[i]] = rk[sa[i - 1]] + (x[sa[i]] != x[sa[i - 1]] || y[sa[i]] != y[sa[i - 1]]);
        }
}
inline void get_height()
{
        int k = 0;
        for (int i = 1; i <= n; i++)
        {
                if (k) --k;
                int j = sa[rk[i] - 1];
                while (s[i + k] == s[j + k]) ++k;
                height[rk[i]] = k;        
        }        
}

int main()
{
        
        scanf("%s%s" , A + 1 , B + 1);
        int t1 = strlen(A + 1) , t2 = strlen(B + 1);
        for (int i = 1; i <= t1; i++) s[++n] = A[i];
        s[++n] = '$';
        for (int i = 1; i <= t2; i++) s[++n] = B[i];
        build_sa();
        get_height();
        int ans = 0;
        for (int i = 2; i <= n; i++)
        {
                if ((sa[i] <= t1 && sa[i - 1] > t1 + 1) || (sa[i] > t1 + 1 && sa[i - 1] <= t1)) 
                        chkmax(ans , height[i]);
        }
        printf("%d
" , ans);
        
        return 0;
    
}
原文地址:https://www.cnblogs.com/evenbao/p/10061624.html