hihocoder1415 后缀数组三·重复旋律3

传送门:http://hihocoder.com/problemset/problem/1415

【题解】

考虑求出两串合在一起(中间加分隔符)后缀数组,就是要求任意在两个串中的$i, j$,$\min\{h_k\} (i \leq k \leq j)$的最大值。

考虑$i, j$一定是满足$|i - j| = 1$且合法的时候最优。

详情见:hihocoder“解题方法提示”

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;
const int mod = 1e9+7;

# define rank RANK

int n, ans;
char ch[M];
int sa[M], rank[M], h[M], t[M];
int tsa[M], cntA[M], cntB[M], A[M], B[M];

inline void    getsa() {
    fill(cntA, cntA + n + 1, 0);
    for (int i=1; i<=n; ++i) cntA[ch[i]] ++;
    for (int i=1; i<=n; ++i) cntA[i] += cntA[i-1];
    for (int i=n; i; --i) sa[cntA[ch[i]] --] = i;
    rank[sa[1]] = 1;
    for (int i=2; i<=n; ++i) {
        rank[sa[i]] = rank[sa[i-1]];
        if(ch[sa[i-1]] != ch[sa[i]]) ++rank[sa[i]];
    }
    for (int len=1; rank[sa[n]] < n; len <<= 1) {
        fill(cntA, cntA + n + 1, 0);
        fill(cntB, cntB + n + 1, 0);
        for (int i=1; i<=n; ++i) {
            cntA[A[i] = rank[i]] ++;
            cntB[B[i] = ((i+len<=n) ? rank[i+len] : 0)] ++;
        }
        for (int i=1; i<=n; ++i) cntA[i] += cntA[i-1], cntB[i] += cntB[i-1];
        for (int i=n; i; --i) tsa[cntB[B[i]] --] = i;
        for (int i=n; i; --i) sa[cntA[A[tsa[i]]] --] = tsa[i];
        rank[sa[1]] = 1;
        for (int i=2; i<=n; ++i) {
            rank[sa[i]] = rank[sa[i-1]];
            if(A[sa[i]] != A[sa[i-1]] || B[sa[i]] != B[sa[i-1]]) ++rank[sa[i]];
        }
    }
}
        
inline void getheight() {
    for (int i=1, j=0; i<=n; ++i) {
        if(j) --j;
        while(ch[i+j] == ch[sa[rank[i]-1] + j]) ++j;
        h[rank[i]] = j;
    }
}


int main() {
    scanf("%s", ch+1);
    n = strlen(ch+1);
    int c = n;
    ch[n+1] = '$';
    scanf("%s", ch+n+2);
    n = strlen(ch+1);
//    printf("%s\n", ch+1);
    getsa(); getheight();
    for (int i=2; i<=n; ++i) {
        int pre, suf;
        pre = sa[i-1], suf = sa[i];
        if(pre > suf) swap(pre, suf);
        if(pre <= c && suf > c) ans = max(ans, h[i]);
    }
    cout << ans;
    return 0;
}
View Code

 

posted @ 2017-07-18 06:46  Galaxies  阅读(225)  评论(0编辑  收藏  举报