문자열 - 아호 코라식(Aho-Corasick)
아호 코라식(Aho-Corasick)에 대해 알아보자.
[3176 도로 네트워크] https://www.acmicpc.net/problem/3176 .
LCA를 구하고 그 때 Sparse table을 이용해보자!
구간 최대, 최소를 구할 때 놀랍게도 전처리를 해두면 O(1)에 구할 수 있는 방법이 있다.
그것이 바로 sparse table이고 최대, 최소는 겹치는 구간이 있어도 상관없기 때문에 겹치는 구간 2개를 이용하는 것이다.
도시와 도로가 트리형태로 주어져있고 한 도시에서 다른 도시로 가는 쿼리가 주어지면 경로 상의 가장 짧은 도로와 가장 긴 도로를 출력하면 된다.
K가 최대 10만이므로 최대 O(N(logN)^2))정도에 해결할 수 있다.
한 도시에서 다른 도시로 간다고 하면 둘의 최소 공통 조상을 무조건 지나기 때문에 LCA를 이용할 수 있다.
lowest common ancester(최소 공통 조상)이다.
제일 가까운 부모라는 것이다.
구하는 방법은 간단하다. 만날 때까지 위로 올리면 된다.
위 논리를 이용한 것이 아래 코드이다.
int LCA(int u, int v){
if(depth[u]<depth[v]) swap(u, v); //u가 더 깊은거라고 하자
int diff = depth[u]-depth[v];
for(int i=0;i<20;i++) if(diff&(1<<i)) u = P[i][u]; //차이 만큼 올라간다.(1번 과정)
if(u==v) return u;
for(int i=19;i>=0;i--) if(P[i][u]!=P[i][v]){ //같아질 떄까지 u, v를 동시에 옮긴다.
u = P[i][u];
v = P[i][v];
}
return P[0][u]; //같아진것을 리턴한다.
}
일단 두 정점사이 길이 하나밖에 없고 LCA는 무조건 지난다.
따라서 sparse table로 최대 최소를 미리 전처리 해두면 LCA를 구하는 과정에서 최대 최소를 구할 수 있을 것이다.
sparse table은 3개를 만들것이고 다음과 같이 정의한다.
위의 코드로 LCA를 구하면 최종적으로 u, v가 같은 상태일때가 아니라 LCA바로 이전 정점들이 된다.
따라서 마지막에 리턴전에 최대, 최소를 한번 더 갱신해 줘야한다.
나머지 주의 할 점은 코드에 주석으로 처리했다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#include <cassert>
#define fast_io cin.tie(NULL); ios_base::sync_with_stdio(false);
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int INF = 987654321;
const int MAX = 100001;
int n, k;
int P[20][MAX], N[20][MAX], X[20][MAX], depth[MAX];
vector<pii> adj[MAX];
void dfs(int here, int parent, int d){
depth[here] = d;
P[0][here] = parent;
for(pii next : adj[here]){
if(next.first==parent) continue;
N[0][next.first] = next.second;
X[0][next.first] = next.second;
dfs(next.first, here, d+1);
}
}
pii LCA(int u, int v){
pii ret;
ret.first = INF;
ret.second = 0;
if(depth[u]<depth[v]) swap(u, v);
int diff = depth[u]-depth[v];
for(int i=0;i<20;i++) if(diff&(1<<i)){ // 깊이를 맞추는 과정
ret.first = min(ret.first, N[i][u]);
ret.second = max(ret.second, X[i][u]);
u = P[i][u];
}
if(u==v){
return ret;
}
for(int i=19;i>=0;i--) if(P[i][u]!=P[i][v]){ // 거슬러 올라가는 과정
ret.first = min(ret.first, N[i][u]);
ret.second = max(ret.second, X[i][u]);
u = P[i][u];
ret.first = min(ret.first, N[i][v]);
ret.second = max(ret.second, X[i][v]);
v = P[i][v];
}
//마지막에 갱신을 하고 리턴해야함
ret.first = min(ret.first, N[0][u]);
ret.second = max(ret.second, X[0][u]);
ret.first = min(ret.first, N[0][v]);
ret.second = max(ret.second, X[0][v]);
return ret;
}
int main(){
fast_io
cin >> n;
for(int i=1;i<n;i++){
int u, v, c;
cin >> u >> v >> c;
adj[u].push_back({v, c});
adj[v].push_back({u, c});
}
dfs(1, 1, 1);
N[0][1] = INF;
for(int j=1;j<20;j++){ //전처리 과정 O(NlogN)
for(int i=1;i<=n;i++){
P[j][i] = P[j-1][P[j-1][i]];
N[j][i] = min(N[j-1][i], N[j-1][P[j-1][i]]);
X[j][i] = max(X[j-1][i], X[j-1][P[j-1][i]]);
}
}
cin >> k;
for(int i=0;i<k;i++){ //O(KlogN)
int u, v; cin >> u >> v;
pii res = LCA(u, v);
cout << res.first << ' ' << res.second << '\n';
}
}
아호 코라식(Aho-Corasick)에 대해 알아보자.
docker를 이해해보자
2060 염소줄서기 풀이 및 코드
분할정복을 이용한 다이나믹 프로그래밍 최적화
코드포스 다시 열심히! 블로그도 열심히!
rust 공부시작!
코드포스 블루 달성 후기
여름캠프 및 SUAPC 후기
2023-05-25-Edu Codeforce round 149 (Div.2)
2023-05-13-Edu Codeforce round 148 (Div.2)
HLD(Heavy Light Decomposition)
행렬 거듭 제곱
2023-05-02-It takes two
Codeforce round 868 (Div.2)
2월 11일 문제풀이
Codeforces#846, TypeDB Foreces 2023, Codeforces#848 업솔빙
ps5 게임 : 용과같이 제로 리뷰
백준 23877번 Convoluted Intervals 문제풀이
codeforce round #828(div 3), EDU #137(div 2) 업솔빙
codeforce round #823(div 2), #824(div 2) 업솔빙
AtCoder Beginner Contest 270 업솔빙
ps5 게임 : 용과같이 극 1 리뷰
백준 18719번 Binomal 문제풀이
백준 14288번 회사문화4 문제풀이
백준 3308번 Matching 문제풀이
백준 18186번 라면사기(large) 문제풀이
백준 4196번 도미노 문제풀이
백준 3176번 도로 네트워크 문제풀이
백준 16367번 TV Show Game 문제풀이
ps5 게임 : 페르소나 5 더 로열 리뷰
codeforce round #811(div 3), #812(div 2), CodeTon round 2 업솔빙
백준 21162번 뒤집기 K 문제풀이
codeforce round #808(div 2), #803(div 2, virtual) 업솔빙
codeforce round #807(div 2) 업솔빙
백준 10167번 금광 문제풀이
codeforce round #805(div 3), #806(div 4) 업솔빙
백준 18253번 최단경로와 쿼리 문제풀이
에듀 라운드 131 업솔빙
백준 1949번 우수 마을 문제풀이
백준 3665번 최종 순위 문제풀이
Trie 자료구조 이해하기
merge sort를 이용하여 inversion 개수세기
3솔의 벽이 너무 높다..
lazy propagation없이 구간 갱신하기
코드포스 폭망기념 upsolving
백준 11505 구간 곱 구하기 문제풀이
백준 1305 광고 문제풀이
백준 4386 별자리 만들기 문제풀이
백준 4803 트리
백준 2206 벽 부수고 이동하기 문제풀이
백준 2166 다각형의 면적 문제풀이
백준 12015 가장 긴 증가하는 부분 수열2 문제풀이
백준 10986 나머지합 문제풀이
스택 구현하기 ========== 자료구조의 기본이라고 하면 스택 과 큐가 있다 백준 10828번에서 마주친 스택
매우매우 많은 정렬이 있지만 그중 가장 안 어려운 3가지를 공부해보았다.
Leave a comment