티스토리 뷰

문제

https://www.acmicpc.net/problem/9249

 

알고리즘

Suffix Array

 

풀이

LCS문제입니다. 주어진 두 문자열$A, B$를 합친 후 LCP를 구하게 되면 답을 얻을 수 있습니다. 이때 주의해야 할 점이 있습니다. 인접한 LCP를 검사할 때, 하나의 Suffix는 $A$의 일부를 포함해야 하지만, 나머지 Suffix는 $A$를 포함해선 안된다는 점입니다. 이점을 유의하지 않으면 $A$ 또는 $B$ 내에서만 LCP를 뽑아버리므로 두 문자열의 공통부분 문자열을 얻지 못하게 됩니다. 시간 복잡도는 Suffix Array와 LCP를 구해야 하므로 $O(NlogN+N)$입니다.

 

코드

#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define REP(i,n) for(int i=1;i<=n;++i)
#define FAST cin.tie(NULL);cout.tie(NULL); ios::sync_with_stdio(false)
using namespace std;

string A, B, C;
int al, bl, idx, ans;
vector<int> g, ng, ordered, lcp, cnt, sfx;

void getsfx(string& s) {
    int p = 1;
    int n = s.size();
    int mx = max(257, n + 1);
    
    g.resize(n + 1); ng.resize(n + 1);
    sfx.resize(n); ordered.resize(n);

    for (int i = 0;i < n;++i) g[i] = s[i];

    for (int t = 1;t < n;t <<= 1) {
        cnt.clear(); cnt.resize(mx);
        for (int i = 0;i < n;++i) ++cnt[g[min(i + t, n)]];
        for (int i = 1;i < mx;++i) cnt[i] += cnt[i - 1];
        for (int i = n - 1;i >= 0;--i) ordered[--cnt[g[min(i + t, n)]]] = i;
        
        cnt.clear(); cnt.resize(mx);
        for (int i = 0;i < n;++i) ++cnt[g[i]];
        for (int i = 1;i < mx;++i) cnt[i] += cnt[i - 1];
        for (int i = n - 1;i >= 0;--i) sfx[--cnt[g[ordered[i]]]] = ordered[i];
       
        if (p == n) break;
        p = 1;

        auto cmp = [&](int i, int j) {
            if (g[i] == g[j]) return g[i + t] < g[j + t];
            return g[i] < g[j];
        };

        ng[sfx[0]] = 1;

        for (int i = 1;i < n;++i) {
            if (cmp(sfx[i - 1], sfx[i])) ++p,ng[sfx[i]] = ng[sfx[i - 1]] + 1;
            else ng[sfx[i]] = ng[sfx[i - 1]];
        }
        g = ng;
    }

    lcp.resize(n);
    for (int i = 0;i < n;++i) g[sfx[i]] = i;
    for (int i = 0, k = 0;i < n;++i, k = max(k - 1, 0)) {
        if (g[i] == n - 1) continue;
        for (int j = sfx[g[i] + 1];s[i + k] == s[j + k];++k);
        lcp[g[i]] = k;
    }

    for (int i = 0;i < n - 1;++i) {
        if (sfx[i] < al && al < sfx[i + 1]||sfx[i+1]<al&&al<sfx[i]) {
            if (lcp[i] <= al) {
                if (ans < lcp[i]) {
                    ans = lcp[i];
                    idx = sfx[i];
                }
            }
            
        }
    }
}

int main() {
    FAST;
    cin >> A >> B;
    al = A.size();
    bl = B.size();
    C = A + '$' + B;
    getsfx(C);
    cout << ans<<'\n';
    cout << C.substr(idx, ans);
    return 0;
}

'Algorithm' 카테고리의 다른 글

[백준 5446] 용량 부족  (0) 2020.07.24
[백준 3080] 아름다운 이름  (0) 2020.07.21
[백준 11479] 서로 다른 부분 문자열의 개수 2  (0) 2020.07.19
[백준 9248] Suffix Array  (2) 2020.07.18
[백준 13276] Prefix와 Suffix  (0) 2020.07.17
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함