문제링크
https://www.acmicpc.net/problem/1605
1605번: 반복 부분문자열
알파벳 소문자로 이루어진 길이 L인 문자열이 있다. 이 문자열의 부분문자열 중, 적어도 한 번은 반복되는 (다시 말해서, 전체 문자열에서 두 번 이상 나타나는) 부분문자열을 '반복 부분문자열'
www.acmicpc.net
풀이
- 반복 부분문자열의 길이의 최대는 max(lcp[i]) 이다.
코드
- 시간복잡도: O(Nlog2N)
#include <bits/stdc++.h> using namespace std; #define all(v) (v).begin(), (v).end() #define rall(v) (v).rbegin(), (v).rend() int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); auto buildSA = [&](string& s) { int N = s.size(); vector<int> sa(N, 0), r(2 * N, 0), nr(2 * N, 0); for (int i = 0; i < N; ++i) { sa[i] = i; r[i] = s[i]; } for (int d = 1; d < N; d <<= 1) { auto cmp = [&](int i, int j) { return r[i] < r[j] || (r[i] == r[j] && r[i + d] < r[j + d]); }; sort(all(sa), cmp); nr[sa[0]] = 1; for (int i = 1; i < N; ++i) { nr[sa[i]] = nr[sa[i - 1]] + cmp(sa[i - 1], sa[i]); } r = nr; } return sa; }; auto buildLCP = [&](string& s) { int N = s.size(); auto sa = buildSA(s); vector<int> lcp(N), isa(N); for (int i = 0; i < N; ++i) { isa[sa[i]] = i; } for(int k = 0, i = 0;i < N;++i) { if(isa[i]){ for(int j = sa[isa[i]-1]; max(i, j) + k < N && s[i+k] == s[j+k]; ++k); lcp[isa[i]] = (k ? k-- : 0); } } return lcp; }; int L; cin >> L; string s; cin >> s; auto lcp = buildLCP(s); cout << *max_element(lcp.begin() + 1, lcp.end()); }
728x90
'PS > BOJ' 카테고리의 다른 글
백준 6171번: 땅따먹기 (0) | 2022.03.08 |
---|---|
백준 3295번: 단방향 링크 네트워크 (0) | 2022.03.07 |
백준 11479번: 서로 다른 부분 문자열의 개수 2 (0) | 2022.03.07 |
백준 3640번: 제독 (0) | 2022.03.07 |
백준 13263번: 나무 자르기 (0) | 2022.03.06 |