문자열 - 아호 코라식(Aho-Corasick)
아호 코라식(Aho-Corasick)에 대해 알아보자.
에듀라운드가 어려운건지….
에듀라운드는 블루퍼포 이상을 맞아본적이 없는 것 같다.
솔직히 그렇게 큰 차이는 없는데 왜 그러는지는 도저히 모르겠다.
이번 셋은 C까지 매우쉽고 D부터는 좀 어려웠다..
D는 감은 잡았는데 뭔가 구현이 막막해서 못풀었다. (이런 문제 좋아보이는데 많이 풀어보고 싶다. )
팰린드롬이다.
뭔가 나는 잘 못푼 것 같다. (그리 깔끔한 코드가 나오지 않아서 그렇게 생각했다. )
#include <bits/stdc++.h>
#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;
typedef tuple<int, int, int> tiii;
#define xx first
#define yy second
int alpha[26];
int main(){
fast_io
int tt; cin >> tt;
while (tt--) {
string s; cin >> s;
memset(alpha, 0, sizeof(alpha));
for(int i=0;i<s.size();i++){
alpha[s[i]-'a']++;
}
int odd = 0, even = 0;
for(int i=0;i<26;i++){
if(!alpha[i]) continue;
if(alpha[i] & 1){
odd++;
if(alpha[i]!=1) even++;
}
else even++;
}
if(odd>1){
cout << "NO\n";
continue;
}
if(odd<=1&&even>=2){
cout << "YES\n";
continue;
}
if(odd<=1&&even==1){
bool ok = true;
for(int i=0;i<s.size()/2;i++){
if(s[i]!=s[s.size()-1-i]) ok = false;
}
if(ok){
cout << "NO\n";
}else{
cout << "YES\n";
}
}
}
}
좋은 문제 같다. 처음에는 우선순위큐로 접근했는데 단순히 이번경우가 더 작다고 그리디하게 뺴버리면 다음 경우가 최선이 아닐 수 있다. 따라서 정렬된 배열에서 앞에서 몇번, 뒤에서 몇번 빼는지를 모두 세주고 그중 최대값을 찾아주는 것이 옳다.
나는 부분합을 구하고 전체(sum)에서 빼는 식으로 구현했다.
ll res =0;
for(int i=0;i<=k;i++){
res = max(res, sum - psa[2*k-2*i] - (psa[n]-psa[n-i]));
}
이 부분이 가장 핵심적인 부분이다.
#include <bits/stdc++.h>
#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;
typedef tuple<int, int, int> tiii;
#define xx first
#define yy second
int main(){
fast_io
int tt; cin >> tt;
while (tt--) {
int n, k; cin >> n >> k;
vector<ll> a(n+1), psa(n+1);
ll sum = 0;
for(int i=1;i<=n;i++){
cin >> a[i];
sum += a[i];
}
sort(a.begin(), a.end());
for(int i=1;i<=n;i++){
psa[i] = psa[i-1] + a[i];
}
ll res =0;
for(int i=0;i<=k;i++){
res = max(res, sum - psa[2*k-2*i] - (psa[n]-psa[n-i]));
}
cout << res << '\n';
}
}
이 문제는 증가하는 부분, 감소하는 부분을 세는 문제로 바꿀 수 있다.
이를 알아내는 것이 그렇게 어렵지 않다..너무 직관적이기 때문이다.
나는 중간에 같은 부분을 처리하는데에서 이상하게 처리하여서 시간이 좀 걸렸다.
같은 원소는 그냥 가볍게 무시하면 된다.
예를 들어 1 2 2 3 3 3 4 4 4 5 5 3 1 이라는 배열이 있어도 이거는 1 5 1 로 줄일 수 있기 때문이다.
따라서 증가하는 부분 + 감소하는 부분 +1 이 정답이다.
#include <bits/stdc++.h>
#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;
typedef tuple<int, int, int> tiii;
#define xx first
#define yy second
int main(){
fast_io
int tt; cin >> tt;
while (tt--) {
int n; cin >> n;
vector<ll> a(n+1);
for(int i=1;i<=n;i++) cin >> a[i];
a[0] = a[1];
int res = 0;
int state = 0;
for(int i=2;i<=n;i++){
if(a[i]>a[i-1]){
if(state==1){
continue;
}else{
res++;
}
state = 1;
}else if(a[i]==a[i-1]){
continue;
}else{
if(state==-1){
continue;
}else{
res++;
}
state = -1;
}
}
cout << res+1 << '\n';
}
}
이 문제를 1시간 정도 봤는데 못풀었다.
근데 중간에 내 문제를 발견한게….내가 집중을 못하고 있었다.
문제를 읽고 갑자기 침대에 눕질 않나… 물이나 따르러 나가질 않나….
뭔가 문제 이해를 제대로 못했을 때 머리속에 잡념이 생기며 시간을 축내고 있었던 것이다.
2시간은 온전히 집중할 수 있는 내가 될 수 있도록해야겠다. 요즘 집중을 너무 못한다.
공부도 1시간 이상 앉아있기가 힘들다. 이 문제를 고칠 수 있는 방법을 아는 사람은 연락 바란다.
문제는 hard를 기준으로 풀어보겠다.
쨋든 문제를 이해해보면
1부터 k까지 더하는 연산, 빼는 연산을 적절히 하여 최솟값을 가장 크게 만드는 것이다.
일단, 한 원소에 홀수번 연산을 하면 값이 줄어들고, 짝수번 연산을 하면 값이 늘어난다.
따라서 2k가 2n으로 나누어지면 모든 원소의 값을 늘릴 수 있겠지만 그 경우가 아니라면 홀수번 접근하여 -연산을 해야하는 경우가 생길 것이다.
그 때 $+1-2$ 를 하여 -1을 빼주는 것이 이득이다.
여기까지가 내가 떠올린 것이고 집중력이 다해 풀지 못했다. 이제 어떻게 해야할까?
k ≥ n 인데 결국 빼는 연산이 필요한 경우는 제일 작은거랑 고루고루 -1씩 뺐을 때랑 비교해야한다.
제일 작은건 k<n일 떄처럼 구하면 되는데 고루고루 -1씩 뺐을 때가 문제다.
고루고루 -1씩 뺏을 때 최선은 모든 경우가 다 같은경우이다. 그래서 연산을 했을 때 모든 원소를 합한 값을 n으로 나눠가지는 경우와 비교하면 된다.
예를 들어, 2 4 4 5 8의 원소들이 있고 k = 7이라고 해보자. 그러면 일단 각 원소에 7, 6, 5, 4, 3을 더할 것이다.
그리고 나머지 2, 1은 하나는 더하고 하나는 뺄 것이다. 다시 저 원소들에 k = 14라고 해보자. 그러면 14, 13, 12, 11, 10을 더하고 나머지 1부터 9로 생기는 경우는 한 원소에 2개씩 적용시켜 (남은 수+1)/2가 될 것이다. 즉 -5이다. 그러면
\[2+4+4+5+8 (원래 원소합)+ 14+13+12+11+10(n개에 최대 수를 더하고) - \frac{남은 수}{2}\]이런 식으로 된다.
위 수학 공식 블록의 논리를 이해하면 아래 코드도 이해할 수 있다 .
#include <bits/stdc++.h>
#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;
typedef tuple<int, int, int> tiii;
#define xx first
#define yy second
const int INF = 1e9+1;
int main(){
fast_io
int n, q; cin >> n >> q;
vector<ll> a(n), pre(n+1, INF);
ll sum = 0;
for(int i=0;i<n;i++){
cin >> a[i];
sum += a[i];
}
sort(a.begin(), a.end());
for(int i=0;i<n;i++){
pre[i+1] = min(pre[i], a[i]-i);
}
for(int i=0;i<q;i++){
ll k; cin >> k;
if(k<n){
cout << min(pre[k]+k, a[k]) << ' ';
continue;
}
if(k%2 != n%2){
cout << min(min(pre[n-1]+k, a[n-1]), (sum + (k-n+2+k)*(n-1)/2-(k-n+1)/2)/n) << ' ';
}else{
cout << min(pre[n]+k, (sum+(k-n+1+k)*n/2-(k-n)/2)/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