티스토리 뷰
5분안에 마스터 하는것이기 때문에 아주 간결하고 핵심 요약만 말할것이다.
준비물 : hash에 대한 기본 지식, 이분탐색에 대한 기본 지식
1. 이분탐색을 돌린다.
길이가 i인 문자열이 반복으로 나온다면 그 아래는 볼 필요가 없다. 즉 이분탐색이 가능하다.
2. hash테이블을 이용하여 같은 문자열이 있는지 검사한다.
hash테이블을 써서 길이 i인 것들중 같은것이 있는지 체크해준다. (hash에 대한 기본지식은 알고 있기 바란다.)
시간 복잡도는 O(NlogN) 이다
아래의 코드는 3033 번 문제이다.
바로 코드를 보겠다.
#include <bits/stdc++.h>
using namespace std;
const int mod = 100003;
int f(long long x) { // x % mod 를 양수로 만들어주는 함수다.
if(x >= 0) return x % mod;
else return ((-x/mod+1)*mod+x) % mod;
}
int main() {
int n;
char a[200005];
scanf("%d",&n);
scanf("%s",&a);
int lo = 0,hi = n;
while(lo+1 < hi) {
int h = 0,po = 1;
int mid = (lo + hi) >> 1;
vector <int> Hash[mod]; // hash배열 만들기
bool found = false;
for(int i = 0;i <= n-mid;i++) {
if(i == 0) { // 처음이라면
for(int j = 0;j < mid;j++) {
h = f(h+1LL*a[mid-j-1]*po);
if(j < mid-1) po = f(po*2); // 초기의 문자열로 hash값 만들기
}
}
else h = f(2*(h-1LL*a[i-1]*po)+a[i+mid-1]); // 길이가 mid 이고 i번째에서 끝나는 문자열의 해시 값
if(!Hash[h].empty()) { // hash값이 같은 것들은 직접 비교해 본다. (몇개 안한다)
for(int p : Hash[h]) {
bool same = true;
for(int j = 0;j < mid;j++){
if(a[i+j] != a[p+j]) { // 다르면 그냥 break
same = false;
break;
}
}
if(same) {
found = true;
break;
}
}
}
if(found) break;
Hash[h].push_back(i); // hash테이블에 해시 값 h을 넣기
}
if(found) lo = mid; // 찾았으면 더 높은 길이 탐색
else hi = mid; // 없으면 더 낮은 길이 탐색
}
printf("%d",lo);
}
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 수열과 쿼리
- 정렬
- AtCoder
- Offline Dynamic Connectivity
- combination
- 비요뜨 존맛
- 1909
- 오일러 경로
- gunwookim
- 하이퍼
- Rabin-Karp
- DP
- 스택
- 세그먼트 트리
- 앳코더
- hyper
- 간단한 풀이
- 냄새 싫어
- 알고리즘 문제 풀이
- codeforces
- BOJ
- PS
- 비요뜨
- 쿼리
- ABC
- Constructive
- 누적 합
- 김춘배
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함