Post

🧩 Baekjoon 15829 - Hashing

🧩 Baekjoon 15829 - Hashing

문제

APC에 온 것을 ν™˜μ˜ν•œλ‹€. λ§Œμ•½ μ—¬λŸ¬λΆ„μ΄ ν•™κ΅μ—μ„œ 자료ꡬ쑰λ₯Ό μˆ˜κ°•ν–ˆλ‹€λ©΄ ν•΄μ‹œ ν•¨μˆ˜μ— λŒ€ν•΄ 배웠을 것이닀. ν•΄μ‹œ ν•¨μˆ˜λž€ μž„μ˜μ˜ 길이의 μž…λ ₯을 λ°›μ•„μ„œ κ³ μ •λœ 길이의 좜λ ₯을 λ‚΄λ³΄λ‚΄λŠ” ν•¨μˆ˜λ‘œ μ •μ˜ν•œλ‹€. ν•΄μ‹œ ν•¨μˆ˜λŠ” λ¬΄κΆλ¬΄μ§„ν•œ μ‘μš© λΆ„μ•Όλ₯Ό κ°–λŠ”λ°, λŒ€ν‘œμ μœΌλ‘œ 자료의 μ €μž₯κ³Ό 탐색에 쓰인닀.

이 λ¬Έμ œμ—μ„œλŠ” μ—¬λŸ¬λΆ„μ΄ μ•žμœΌλ‘œ μœ μš©ν•˜κ²Œ μ“Έ 수 μžˆλŠ” ν•΄μ‹œ ν•¨μˆ˜λ₯Ό ν•˜λ‚˜ κ°€λ₯΄μ³μ£Όκ³ μž ν•œλ‹€. λ¨Όμ €, νŽΈμ˜μƒ μž…λ ₯으둜 λ“€μ–΄μ˜€λŠ” λ¬Έμžμ—΄μ—λŠ” 영문 μ†Œλ¬Έμž(a, b, …, z)둜만 κ΅¬μ„±λ˜μ–΄μžˆλ‹€κ³  κ°€μ •ν•˜μž. μ˜μ–΄μ—λŠ” 총 26개의 μ•ŒνŒŒλ²³μ΄ μ‘΄μž¬ν•˜λ―€λ‘œ aμ—λŠ” 1, bμ—λŠ” 2, cμ—λŠ” 3, …, zμ—λŠ” 26으둜 κ³ μœ ν•œ 번호λ₯Ό λΆ€μ—¬ν•  수 μžˆλ‹€. 결과적으둜 μš°λ¦¬λŠ” ν•˜λ‚˜μ˜ λ¬Έμžμ—΄μ„ μˆ˜μ—΄λ‘œ λ³€ν™˜ν•  수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄μ„œ λ¬Έμžμ—΄ β€œabba”은 μˆ˜μ—΄ 1, 2, 2, 1둜 λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€.

ν•΄μ‹œ 값을 κ³„μ‚°ν•˜κΈ° μœ„ν•΄μ„œ μš°λ¦¬λŠ” λ¬Έμžμ—΄ ν˜Ήμ€ μˆ˜μ—΄μ„ ν•˜λ‚˜μ˜ μ •μˆ˜λ‘œ μΉ˜ν™˜ν•˜λ €κ³  ν•œλ‹€. κ°„λ‹¨ν•˜κ²ŒλŠ” μˆ˜μ—΄μ˜ 값을 λͺ¨λ‘ 더할 μˆ˜λ„ μžˆλ‹€. ν•΄μ‹œ ν•¨μˆ˜μ˜ μ •μ˜μ—μ„œ μœ ν•œν•œ λ²”μœ„μ˜ 좜λ ₯을 κ°€μ Έμ•Ό ν•œλ‹€κ³  ν–ˆμœΌλ‹ˆκΉŒ μ λ‹Ήνžˆ 큰 수 M으둜 λ‚˜λˆ μ£Όμž. μ§œμž”! ν•΄μ‹œ ν•¨μˆ˜κ°€ μ™„μ„±λ˜μ—ˆλ‹€. 이λ₯Ό μˆ˜μ‹μœΌλ‘œ ν‘œν˜„ν•˜λ©΄ μ•„λž˜μ™€ κ°™λ‹€.

ν•΄μ‹œ ν•¨μˆ˜μ˜ μž…λ ₯으둜 λ“€μ–΄μ˜¬ 수 μžˆλŠ” λ¬Έμžμ—΄μ˜ μ’…λ₯˜λŠ” λ¬΄ν•œν•˜μ§€λ§Œ 좜λ ₯ λ²”μœ„λŠ” μ •ν•΄μ Έμžˆλ‹€. λ‹€λ“€ λΉ„λ‘˜κΈ° μ§‘μ˜ 원리에 λŒ€ν•΄μ„œλŠ” ν•œ 번쯀 듀어봀을 것이닀. κ·Έ 원리에 μ˜ν•˜λ©΄ μ„œλ‘œ λ‹€λ₯Έ λ¬Έμžμ—΄μ΄λ”λΌλ„ λ™μΌν•œ ν•΄μ‹œ 값을 κ°€μ§ˆ 수 μžˆλ‹€. 이λ₯Ό ν•΄μ‹œ 좩돌이라고 ν•˜λŠ”λ°, 쒋은 ν•΄μ‹œ ν•¨μˆ˜λŠ” μ΅œλŒ€ν•œ 좩돌이 적게 μΌμ–΄λ‚˜μ•Ό ν•œλ‹€. μœ„μ—μ„œ μ •μ˜ν•œ ν•΄μ‹œ ν•¨μˆ˜λŠ” μ•ŒνŒŒλ²³μ˜ μˆœμ„œλ§Œ 바꿔도 좩돌이 μΌμ–΄λ‚˜κΈ° λ•Œλ¬Έμ— λ‚˜μœ ν•΄μ‹œ ν•¨μˆ˜μ΄λ‹€. κ·ΈλŸ¬λ‹ˆκΉŒ 쑰금 더 κ°œμ„ ν•΄λ³΄μž. μ–΄λ–»κ²Œ ν•˜λ©΄ μˆœμ„œκ°€ λ‹¬λΌμ‘Œμ„λ•Œ 좜λ ₯값도 λ‹¬λΌμ§€κ²Œ ν•  수 μžˆμ„κΉŒ? 머리λ₯Ό ꡴리면 μˆ˜μ—΄μ˜ 각 ν•­λ§ˆλ‹€ κ³ μœ ν•œ κ³„μˆ˜λ₯Ό λΆ€μ—¬ν•˜λ©΄ λœλ‹€λŠ” 아이디어λ₯Ό 생각해볼 수 μžˆλ‹€. κ°€μž₯ λŒ€ν‘œμ μΈ 방법은 ν•­μ˜ λ²ˆν˜Έμ— ν•΄λ‹Ήν•˜λŠ” 만큼 νŠΉμ •ν•œ 숫자λ₯Ό κ±°λ“­μ œκ³±ν•΄μ„œ κ³±ν•΄μ€€ λ‹€μŒ λ”ν•˜λŠ” 것이 μžˆλ‹€. 이λ₯Ό μˆ˜μ‹μœΌλ‘œ ν‘œν˜„ν•˜λ©΄ μ•„λž˜μ™€ κ°™λ‹€.

보톡 rκ³Ό M은 μ„œλ‘œμ†ŒμΈ 숫자둜 μ •ν•˜λŠ” 것이 μΌλ°˜μ μ΄λ‹€. μš°λ¦¬κ°€ 직접 μ •ν•˜λΌκ³  ν•˜λ©΄ νž˜λ“€ν…Œλ‹ˆκΉŒ r의 값은 26보닀 큰 μ†Œμˆ˜μΈ 31둜 ν•˜κ³  M의 값은 1234567891(λ†€λžκ²Œλ„ μ†Œμˆ˜μ΄λ‹€!!)둜 ν•˜μž. 이제 μ—¬λŸ¬λΆ„μ΄ ν•  일은 μœ„ 식을 톡해 μ£Όμ–΄μ§„ λ¬Έμžμ—΄μ˜ ν•΄μ‹œ 값을 κ³„μ‚°ν•˜λŠ” 것이닀. 그리고 이 ν•¨μˆ˜λŠ” 간단해 보여도 자주 μ“°μ΄λ‹ˆκΉŒ κΈ°μ–΅ν•΄λ’€λ‹€κ°€ 잘 써먹도둝 ν•˜μž.

μž…λ ₯

첫 μ€„μ—λŠ” λ¬Έμžμ—΄μ˜ 길이 L이 λ“€μ–΄μ˜¨λ‹€. λ‘˜μ§Έ μ€„μ—λŠ” 영문 μ†Œλ¬Έμžλ‘œλ§Œ 이루어진 λ¬Έμžμ—΄μ΄ λ“€μ–΄μ˜¨λ‹€. μž…λ ₯으둜 μ£Όμ–΄μ§€λŠ” λ¬Έμžμ—΄μ€ λͺ¨λ‘ μ•ŒνŒŒλ²³ μ†Œλ¬Έμžλ‘œλ§Œ κ΅¬μ„±λ˜μ–΄ μžˆλ‹€.

좜λ ₯

λ¬Έμ œμ—μ„œ μ£Όμ–΄μ§„ ν•΄μ‹œν•¨μˆ˜μ™€ μž…λ ₯으둜 μ£Όμ–΄μ§„ λ¬Έμžμ—΄μ„ μ‚¬μš©ν•΄ κ³„μ‚°ν•œ ν•΄μ‹œ 값을 μ •μˆ˜λ‘œ 좜λ ₯ν•œλ‹€.

Small(50점)

  • - 1 ≀ L ≀ 5

Large(50점)

  • - 1 ≀ L ≀ 50

예제

βœ… μž…λ ₯ 1

1
2
5
abcde

βœ… 좜λ ₯ 1

1
4739715

βœ… μž…λ ₯ 2

1
2
3
zzz

βœ… 좜λ ₯ 2

1
25818

βœ… μž…λ ₯ 3

1
2
1
i

βœ… 좜λ ₯ 3

1
9

μž‘μ„± μ½”λ“œ 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStreamReader;  
  
public class Main {  
	private static int M = 1_234_567_891;  
	
	public static void main(String[] args) throws IOException {  
		// 1. λ³€μˆ˜ μ„ μ–Έ 및 μ΄ˆκΈ°ν™”  
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));  
		int l = Integer.parseInt(br.readLine());  
		String s = br.readLine();  
		int i = 0;  
		int result = 0;  
		
		// 2. λ¬Έμžμ—΄ 순회  
		for (char c : s.toCharArray()) {  
			int a = (int)c - 96;  
			result += a * (int)Math.pow(31, i++) % M;  
		}  
		
		// 3. 좜λ ₯  
		System.out.println(result);  
	}  
}
  • 50점 짜리 정닡이닀.
  • result 값을 κ΅¬ν•˜λŠ” κ³Όμ •μ—μ„œ μ˜€λ²„ν”Œλ‘œμš°κ°€ λ°œμƒν•˜λŠ” κ²ƒμœΌλ‘œ 보인닀.

μž‘μ„± μ½”λ“œ 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    private static final int R = 31;
    private static final int M = 1_234_567_891;
    
    public static void main(String[] args) throws IOException {
        // 1. λ³€μˆ˜ μ„ μ–Έ 및 μ΄ˆκΈ°ν™”
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int l = Integer.parseInt(br.readLine());
        String s = br.readLine();
        long result = 0;
        long pow = 1;
        
        // 2. λ¬Έμžμ—΄ 순회
        for (int i = 0; i < l; i++) {
            int val = s.charAt(i) - 'a' + 1;
            result = (result + val * pow) % M;
            pow = (pow * R) % M;
        }
        
        // 3. 좜λ ₯
        System.out.println(result);
    }
}
  • ν•΄λ‹Ή 문제λ₯Ό ν•΄κ²°ν•˜λ €λ©΄ λͺ¨λ“ˆλŸ¬ μ—°μ‚°μ˜ 뢄배법칙을 이해해야 ν•œλ‹€.
  • μ΅œμ’… κ²°κ³Όμ—λ§Œ λͺ¨λ“ˆλŸ¬ 연산을 μ μš©ν•΄λ„ λ˜μ§€λ§Œ 쀑간 κ³Όμ •μ—μ„œ 각 행에 λͺ¨λ“ˆλŸ¬ 연산을 μ μš©ν•΄λ„ κ²°κ³ΌλŠ” 달라지지 μ•Šκ³ , μ˜€λ²„ν”Œλ‘œμš° λ°©μ§€λ₯Ό μœ„ν•΄μ„œλŠ” ν•„μš”ν•œ μ²˜λ¦¬μ΄λ‹€.
This post is licensed under CC BY 4.0 by the author.