ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 1062번 - 가르침
    알고리즘/백준 2023. 8. 17. 03:01

    1️⃣ 비트마스킹

     

    ✏️ 풀이 과정

    정보의 형태를 변환하면 생각보다 가짓수가 적게 나오는 문제입니다. 어떤 알파벳이 등장하는 지가 중요하기 때문에 문장이 주어지면 이를 비트마스킹을 이용해서 어떤 알파벳들이 쓰였는지에 대한 정보로 바꿀 수 있습니다. 알파벳이 총 26개이기 때문에 26bit 안으로 간단하게 변환이 가능합니다.(가령 a가 있으면 1<<0에 표시 b가 있으면 1<<1에 표시)

     

    이 정보들을 구했다면 나머지는 K개의 알파벳을 사용하는 가능한 모든 조합과 비교해서 가장 해당 조합이 포괄하는 단어가 많은 경우를 구하면 됩니다. 이는 비트 연산자 &를 이용해서 간단하게 구현할 수 있습니다.

     

    처음에 저장해놓은 모든 정보들에 대해 조합 결과를 비트마스킹으로 변환한 결과와 AND연산을 했을 때 해당 정보가 그대로 유지되면(즉 조합 결과의 해당 부분이 모두 1일 때) 카운팅을 해주면 됩니다.

     

    각 조합마다 카운팅을 해주면서 최댓값을 갱신하면 문제가 해결됩니다.

     

    여기서 a, n, t, i, c의 5개의 알파벳은 고정이기 때문에 이를 미리 고려하고 시작하면 계산 횟수를 크게 줄일 수 있습니다.

     

    ⏱ 시간 복잡도

    조합을 사용해서 전체 경우의 수를 따져 N개의 수와 비교하는 부분이 핵심이기 때문에 시간 복잡도는 O(21^(K-5) * N)이 됩니다.

     

    💻 코드

    JavaScript

    const input = require("fs")
        .readFileSync(process.platform === "linux" ? "/dev/stdin" : "input.txt")
        .toString()
        .trim()
        .split("\n");
    
    const [N, K] = input[0].split(" ").map(Number);
    const words = [];
    for (let i = 1; i <= N; i++) {
        let bit = 0;
        const str = input[i];
        for (let j = 0; j < str.length; j++) {
            for (let k = 0; k < 26; k++) {
                if (str.charCodeAt(j) === "a".charCodeAt(0) + k) {
                    bit |= 1 << k;
                }
            }
        }
        words.push(bit);
    }
    let ans = 0;
    let origin = 0;
    const init = [0, 2, 8, 13, 19];
    init.forEach((item) => {
        origin |= 1 << item;
    });
    const R = K - 5;
    
    const rest = [
        1, 3, 4, 5, 6, 7, 9, 10, 11, 12, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25,
    ];
    let res = [];
    
    const comb = (n, start) => {
        if (n === R) {
            let tmp = origin;
            res.forEach((item) => {
                tmp |= 1 << item;
            });
            let cnt = 0;
            words.forEach((word) => {
                if ((word & tmp) === word) {
                    cnt++;
                }
            });
            if (cnt > ans) {
                ans = cnt;
            }
            return;
        }
    
        for (let i = start; i < 21; i++) {
            res[n] = rest[i];
            comb(n + 1, i + 1);
        }
    };
    
    comb(0, 0);
    console.log(ans);

    '알고리즘 > 백준' 카테고리의 다른 글

    16566번 - 카드 게임  (1) 2023.08.22
    16236번 - 아기 상어  (0) 2023.08.20
    14391번 - 종이 조각  (0) 2023.08.17
    10830번 - 행렬 제곱  (0) 2023.08.09
    9935번 - 문자열 폭발  (0) 2023.08.09
Designed by Tistory.