개인적으로 재밌는 문제였다. 내가 비트마스킹을 잘 몰랐기도 했지만 풀이시간이 오래걸렸다.
문제의 메커니즘은 비교적 간단했지만 비트열에서 1, 0으로 바꾸는 과정이 생소하여 더뎠었다.
고찰
이 문제에 비트마스킹으로 접근한 이유는 다음과 같다.
- 전체 집합을 비트열로 나타낼 수 있다.
- 알파벳은 26개이므로 32비트 정수의 비트열에서 다음과 같이 표현할 수 있다.
0000 0011 1111 1111 1111 1111 1111 1111
0000 00zy xwvu tsrq ponm lkji hgfe dcba
- 알파벳은 26개이므로 32비트 정수의 비트열에서 다음과 같이 표현할 수 있다.
- 선택지로 주어진 집합들을 비트열로 취급할 수 있다.
- 예를 들어 apple은 문제의 조건에서 중복을 고려하지 않기 때문에 {a, p, l, e}로 생각해볼 수 있고, 각각의 알파벳에 해당하는 비트들을 1로, 그 외의 비트들은 0으로 마스킹한 합으로 단어를 표현할 수 있다.
- 입력이 단순하다.
- 특정 알파벳을 잊어버리거나, 기억이 나는건 특정 비트열을 0 또는 1로 하는 것과 같다.
즉, 저장하고 있는 비트열에서 입력으로 들어온 비트열을 처리하고 단어 (특정 비트열)와 비교하면 표현여부를 알 수 있다.
- 특정 알파벳을 잊어버리거나, 기억이 나는건 특정 비트열을 0 또는 1로 하는 것과 같다.
1, 2번은 고려했지만 3번은 고려하지 못하여 다소 지저분한 코드로 해결했다. 주어진 조건들을 어떻게 표현할 수 있을지 고민해보는게 필요한 것 같다.
정답 코드 (수정이 필요함)
더보기
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#define BIT_MASK 0x7fffffff
int N, M;
int substi(const string& str)
{
int num = 0;
for (const auto& item : str) {
num |= BIT_MASK & (1 << item - 'a');
}
return num;
}
void oper(int idx, char c, vector<int>& v, const vector<int>& org)
{
int len = v.size();
for (int i = 0; i < len; i++) {
if (idx == 1) {
v[i] = v[i] & ~(1 << c - 'a');
}
else {
v[i] |= org[i] & (1 << c - 'a');
}
}
}
int main()
{
string s;
cin >> N >> M;
vector<int> v(N, 0);
vector<int> org(N, 0);
for (int i = 0; i < N; i++) {
cin >> s;
v[i] = substi(s);
}
org = v;
int op, cnt = 0;
char c;
for (int i = 0; i < M; i++) {
cin >> op >> c;
oper(op, c, v, org);
for (int j = 0; j < org.size(); j++) {
if (v[j] == org[j]) {
++cnt;
}
}
printf("%d\n", cnt);
cnt = 0;
}
return 0;
}
'알고리즘 관련 > BOJ' 카테고리의 다른 글
2751 수 정렬하기 2 (0) | 2020.12.20 |
---|---|
2638 치즈 (0) | 2020.12.19 |
16953 A → B (0) | 2020.12.18 |
2096 내려가기 (0) | 2020.12.18 |
2294 동전 2 (0) | 2020.12.17 |