백준 저지에서 문자 해독을 자바를 통해 풀어 보았다.
GitHub - tomy9729/Algorithm: 🐗 내가 직접 작성한 내 코드 🐗
🐗 내가 직접 작성한 내 코드 🐗. Contribute to tomy9729/Algorithm development by creating an account on GitHub.
github.com
https://www.acmicpc.net/problem/1593
1593번: 문자 해독
첫째 줄에 고고학자들이 찾고자 하는 단어 W의 길이 g와 발굴된 벽화에서 추출한 문자열 S의 길이 |S|가 빈 칸을 사이에 두고 주어진다. (1≤g≤3000, g≤|S|≤3,000,000) 둘째 줄에 W, 셋째 줄에 S의 실
www.acmicpc.net
1593번 문자 해독
문제
마야 문자를 해독하는 일은 예상 외로 어려운 일이다. 현재에도 뜻이 완전히 밝혀진 마야 문자는 거의 없는 실정이며, 그나마 해독에 진척이 시작된 지는 30여 년도 되지 않았다.
마야 문자는 소리를 나타내는 여러 종류의 그림글자로 구성되는데, 이 글자들이 여러 위치에서 결합함으로써 단어를 형성한다.
마야 문자 해독을 어렵게 하는 요인 중 하나는 바로 단어를 읽는 순서이다. 마야 문자를 쓰는 고대인들은 단어를 기록할 때 특정한 규칙 대신, 그들이 보기에 좋게 보이도록 단어를 이루는 글자들을 아무렇게나 배열했다. 그렇기 때문에 고고학자들이 마야 기록에서 단어를 이루는 각 그림글자들의 발음을 알아내더라도 그 단어를 실제로 발음하는 방법은 정확히 알 수 없는 셈이다.
고고학자들은 W라는 특정 단어를 발굴 기록으로부터 찾고 있다. 그 단어를 구성하는 각 글자들은 무엇인지 알고 있지만, 이것이 고대 기록에 어떤 형태로 숨어 있는지는 다 알지 못한다.
W를 이루고 있는 g개의 그림문자와, 연구 대상인 벽화에 기록된 마야 문자열 S가 주어졌을 때, 단어 W가 마야 문자열 S에 들어있을 수 있는 모든 가짓수를 계산하는 프로그램을 작성하시오. 즉, 문자열 S안에서 문자열 W의 순열 중 하나가 부분 문자열로 들어있는 모든 경우의 수를 계산하라는 뜻이다.
설명
map 2개와 슬라이딩 윈도우를 통해 풀었다.
한 map(A)에는 W에 적힌 알파벳을 key로 나오는 빈도를 value로 저장했다.
다른 map(B)에는 W에 적힌 알파벳을 key로 value는 전부 0으로 저장했다.
S에 대해서 반복문을 돈다. index가 g보다 작을 때는 추가만 하고, 그렇지 않을 때는 앞 문자는 빼고 뒤 문자는 추가한다.
이 때 앞문자를 뺄 때 map에 포함되어 있다면 앞문자를 key로 가지는 value를 -1 해주고, 뒤문자를 더 할 때 map에 포함되어 있다면 뒤문자를 key로 가지는 value를 +1해준다.
-1이나 +1을 할 때 전체 길이를 저장하는 변수 count에 대해서도 -1 혹은 +1을 해준다.
만약 count가 g와 같을 때 map(A)와 map(B)가 완전히 같은지를 확인한다. 만약 같다면 W의 순열이 S의 부분집합으로 존재하는 경우이다. 이 때마다 answer를 카운팅해준다.
코드
//1593번 문자 해독.java
package boj20220113;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.StringTokenizer;
public class 문자_해독_1593 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer st;
static StringBuilder sb = new StringBuilder();
public static void main(String[] args) throws IOException {
st = new StringTokenizer(br.readLine(), " ");
int g = Integer.parseInt(st.nextToken());
int sLength = Integer.parseInt(st.nextToken());
String W = br.readLine();
String S = br.readLine();
int count=0;
int answer=0;
HashMap<Character, Integer> max = new HashMap<>();
HashMap<Character, Integer> map = new HashMap<>();
for(int i=0;i<g;i++) {
Character c = new Character(W.charAt(i));
if(map.containsKey(c)) {
max.put(c, max.get(c)+1);
}
else {
max.put(c, 1);
map.put(c, 0);
}
}
Character head;
Character tail;
for(int i=0;i<sLength;i++) {
if(i<g) {
tail = new Character(S.charAt(i));
if(map.containsKey(tail)) {
count++;
map.put(tail, map.get(tail)+1);
}
}
else {
//head삭제
head = new Character(S.charAt(i-g));
if(map.containsKey(head)) {
count--;
map.put(head, map.get(head)-1);
}
//tail추가
tail = new Character(S.charAt(i));
if(map.containsKey(tail)) {
count++;
map.put(tail, map.get(tail)+1);
}
}
if(count==g) {
boolean check = true;
for(Character c : max.keySet()) {
if(max.get(c)!=map.get(c)) {
check=false;
break;
}
}
if(check) {
answer++;
}
}
}
System.out.println(answer);
}
}
'Problem Solving > 백준BOJ' 카테고리의 다른 글
[백준BOJ] 1296번 대칭 차집합.js (0) | 2022.06.19 |
---|---|
[백준BOJ] 7609번 회문.java (0) | 2022.01.14 |
[백준BOJ] 12764번 싸지방에 간 준하.java (0) | 2022.01.05 |
[백준BOJ] 17070번 파이프 옮기기 1.java (0) | 2021.12.30 |
[백준BOJ] 16953번 A->B.java (0) | 2021.12.28 |