[白俊]18119単語暗記
📌 質問する
俊碩は英語の単語を暗記しなければならない.辞書にはN語ある.すべての単語は小文字です.単語のすべてのアルファベットを知っていると、その単語を完全に知っていると言います.
次のクエリが表示されます.
1 x:アルファベットxを忘れます.
2 x:アルファベットxを覚えます.
最初はすべてのアルファベットを覚えた状態で、母音は完璧に暗記されているので、絶対に忘れません.
各クエリーは、完全に知っている単語の数を出力します.
✔入力
1行目は整数N(1≦N≦10^4)とM(1≦M≦5)である.×10^4).
次のN行に文字列があります.文字列の長さは10^3を超えません.
次のM行の整数oと文字xの各行.oは1,2の1つで、xは小文字です.
oが1であればxを忘れることを意味し、oは2を覚えることを意味する.oが1の場合はxを覚え、oが2の場合はxを忘れることを保証します.
✔方法
問題ばかり見ていると、あまり難しくないような気がします.ただし、MクエリーごとにN個の整数をチェックする場合は、5×10^4*10^4の5億以上の演算が必要です...制限時間は4秒です.一般的な探求は問題を解くことができない.
「ビットマスク」を使えば、問題を解く可能性はずっと高い.
理解すべき演算は以下の通りです.1に対して27の左シフト演算を実行すると、27ビット目に1を生成し、残りのビットは0のビットである.
このとき、1を削除すると、いずれも1の26ビット数が生成される.
現在の値をcurと呼ぶ場合、現在の値(「c」-「a」)の値は3であり、1<(「c」-「a」)の値は1000である.
この値をcurおよび|(または)演算すると、現在の値のcの位置が1に変更されます.
問題では、入力したアルファベット値が含まれていることを意味します. のターゲットアルファベット値を~(not)演算すると、ターゲットアルファベットのビット値は0に変更され、残りは1に変更されます.
この値とalph値を&(and)に演算すると、対応するターゲットアルファベット値の桁数が0に変更されます.
問題では、値を忘れたことを示します. ✔コード
ビット演算をよく知っていれば簡単に解けるが、慣れていないので、時間をかけてビット演算を復習することができる.
ビット演算を実行せずに上記の論理と同じようにコードを記述することもでき、より複雑になるため、ビット演算を用いてコードを記述することができる.
ソース:https://www.acmicpc.net/problem/18119
俊碩は英語の単語を暗記しなければならない.辞書にはN語ある.すべての単語は小文字です.単語のすべてのアルファベットを知っていると、その単語を完全に知っていると言います.
次のクエリが表示されます.
1 x:アルファベットxを忘れます.
2 x:アルファベットxを覚えます.
最初はすべてのアルファベットを覚えた状態で、母音は完璧に暗記されているので、絶対に忘れません.
各クエリーは、完全に知っている単語の数を出力します.
✔入力
1行目は整数N(1≦N≦10^4)とM(1≦M≦5)である.×10^4).
次のN行に文字列があります.文字列の長さは10^3を超えません.
次のM行の整数oと文字xの各行.oは1,2の1つで、xは小文字です.
oが1であればxを忘れることを意味し、oは2を覚えることを意味する.oが1の場合はxを覚え、oが2の場合はxを忘れることを保証します.
✔方法
問題ばかり見ていると、あまり難しくないような気がします.ただし、MクエリーごとにN個の整数をチェックする場合は、5×10^4*10^4の5億以上の演算が必要です...制限時間は4秒です.一般的な探求は問題を解くことができない.
「ビットマスク」を使えば、問題を解く可能性はずっと高い.
理解すべき演算は以下の通りです.
int alph = (1 << 27) - 1
このとき、1を削除すると、いずれも1の26ビット数が生成される.
cur |= 1 << ('c' -'a');
この値をcurおよび|(または)演算すると、現在の値のcの位置が1に変更されます.
問題では、入力したアルファベット値が含まれていることを意味します.
alph &= ~(1 << (target-'a'));
この値とalph値を&(and)に演算すると、対応するターゲットアルファベット値の桁数が0に変更されます.
問題では、値を忘れたことを示します.
import java.util.Scanner;
//단어 암기
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//문자열의 수
int n = sc.nextInt();
//쿼리 의 수
int m = sc.nextInt();
//1로 초기화된 26자리 비트
int alph = (1 << 27) - 1;
//단어를 담는 배열
int[] words = new int[n];
for(int i = 0; i < n; i++) {
String word = sc.next();
// 각단어의 알파벳 위치만 1로 변경
for(char c : word.toCharArray())
words[i] |= 1 << (c -'a');
}
for(int i = 0; i < m; i++) {
int o = sc.nextInt();
char target = sc.next().charAt(0);
//잊는다
if(o == 1) {
//target위치의 값만 0으로 바꾸고 & 연산자를 통해 그 부분의 alph비트 값을 0으로 변경
alph &= ~(1 << (target-'a'));
}
//기억한다
else {
alph |= (1 << (target-'a'));
}
int count = 0;
for(int j = 0; j < words.length; j++) {
//alph와 word연산한 값이 word보다 같거나 크면 모든 알바펫을 알고 있는 것으로 단어를 아는 것.
if((alph & words[j]) >= words[j]) {
count++;
}
}
System.out.println(count);
}
}
}
🖋 振り返るビット演算をよく知っていれば簡単に解けるが、慣れていないので、時間をかけてビット演算を復習することができる.
ビット演算を実行せずに上記の論理と同じようにコードを記述することもでき、より複雑になるため、ビット演算を用いてコードを記述することができる.
ソース:https://www.acmicpc.net/problem/18119
Reference
この問題について([白俊]18119単語暗記), 我々は、より多くの情報をここで見つけました https://velog.io/@6v6/백준-18119-단어암기テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol