Algorithm

[λ°±μ€€] 15829번 - Hashing (C++)

moaoh 2024. 11. 11. 23:46

https://www.acmicpc.net/problem/15829

 

 

 

문제

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

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

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

β€ŠH=∑i=0l−1aimodMβ€Š

ν•΄μ‹œ ν•¨μˆ˜μ˜ μž…λ ₯으둜 λ“€μ–΄μ˜¬ 수 μžˆλŠ” λ¬Έμžμ—΄μ˜ μ’…λ₯˜λŠ” λ¬΄ν•œν•˜μ§€λ§Œ 좜λ ₯ λ²”μœ„λŠ” μ •ν•΄μ Έμžˆλ‹€. λ‹€λ“€ λΉ„λ‘˜κΈ° μ§‘μ˜ 원리에 λŒ€ν•΄μ„œλŠ” ν•œ 번쯀 듀어봀을 것이닀. κ·Έ 원리에 μ˜ν•˜λ©΄ μ„œλ‘œ λ‹€λ₯Έ λ¬Έμžμ—΄μ΄λ”λΌλ„ λ™μΌν•œ ν•΄μ‹œ 값을 κ°€μ§ˆ 수 μžˆλ‹€. 이λ₯Ό ν•΄μ‹œ 좩돌이라고 ν•˜λŠ”λ°, 쒋은 ν•΄μ‹œ ν•¨μˆ˜λŠ” μ΅œλŒ€ν•œ 좩돌이 적게 μΌμ–΄λ‚˜μ•Ό ν•œλ‹€. μœ„μ—μ„œ μ •μ˜ν•œ ν•΄μ‹œ ν•¨μˆ˜λŠ” μ•ŒνŒŒλ²³μ˜ μˆœμ„œλ§Œ 바꿔도 좩돌이 μΌμ–΄λ‚˜κΈ° λ•Œλ¬Έμ— λ‚˜μœ ν•΄μ‹œ ν•¨μˆ˜μ΄λ‹€. κ·ΈλŸ¬λ‹ˆκΉŒ 쑰금 더 κ°œμ„ ν•΄λ³΄μž.

μ–΄λ–»κ²Œ ν•˜λ©΄ μˆœμ„œκ°€ λ‹¬λΌμ‘Œμ„λ•Œ 좜λ ₯값도 λ‹¬λΌμ§€κ²Œ ν•  수 μžˆμ„κΉŒ? 머리λ₯Ό ꡴리면 μˆ˜μ—΄μ˜ 각 ν•­λ§ˆλ‹€ κ³ μœ ν•œ κ³„μˆ˜λ₯Ό λΆ€μ—¬ν•˜λ©΄ λœλ‹€λŠ” 아이디어λ₯Ό 생각해볼 수 μžˆλ‹€. κ°€μž₯ λŒ€ν‘œμ μΈ 방법은 ν•­μ˜ λ²ˆν˜Έμ— ν•΄λ‹Ήν•˜λŠ” 만큼 νŠΉμ •ν•œ 숫자λ₯Ό κ±°λ“­μ œκ³±ν•΄μ„œ κ³±ν•΄μ€€ λ‹€μŒ λ”ν•˜λŠ” 것이 μžˆλ‹€. 이λ₯Ό μˆ˜μ‹μœΌλ‘œ ν‘œν˜„ν•˜λ©΄ μ•„λž˜μ™€ κ°™λ‹€.

β€ŠH=∑i=0l−1airimodMβ€Š

보톡 rκ³Ό M은 μ„œλ‘œμ†ŒμΈ 숫자둜 μ •ν•˜λŠ” 것이 μΌλ°˜μ μ΄λ‹€. μš°λ¦¬κ°€ 직접 μ •ν•˜λΌκ³  ν•˜λ©΄ νž˜λ“€ν…Œλ‹ˆκΉŒ r의 값은 26보닀 큰 μ†Œμˆ˜μΈ 31둜 ν•˜κ³  M의 값은 1234567891(λ†€λžκ²Œλ„ μ†Œμˆ˜μ΄λ‹€!!)둜 ν•˜μž.

이제 μ—¬λŸ¬λΆ„μ΄ ν•  일은 μœ„ 식을 톡해 μ£Όμ–΄μ§„ λ¬Έμžμ—΄μ˜ ν•΄μ‹œ 값을 κ³„μ‚°ν•˜λŠ” 것이닀. 그리고 이 ν•¨μˆ˜λŠ” 간단해 보여도 자주 μ“°μ΄λ‹ˆκΉŒ κΈ°μ–΅ν•΄λ’€λ‹€κ°€ 잘 써먹도둝 ν•˜μž.

μž…λ ₯

첫 μ€„μ—λŠ” λ¬Έμžμ—΄μ˜ 길이 L이 λ“€μ–΄μ˜¨λ‹€. λ‘˜μ§Έ μ€„μ—λŠ” 영문 μ†Œλ¬Έμžλ‘œλ§Œ 이루어진 λ¬Έμžμ—΄μ΄ λ“€μ–΄μ˜¨λ‹€.

μž…λ ₯으둜 μ£Όμ–΄μ§€λŠ” λ¬Έμžμ—΄μ€ λͺ¨λ‘ μ•ŒνŒŒλ²³ μ†Œλ¬Έμžλ‘œλ§Œ κ΅¬μ„±λ˜μ–΄ μžˆλ‹€.

좜λ ₯

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

Small (50점)

  • 1 ≤ L ≤ 5

Large (50점)

  • 1 ≤ L ≤ 50

 

풀이과정

문제의 풀이식은 μƒλ‹Ήνžˆ κ°„λ‹¨ν•˜λ‹€.

μœ„μ™€ 같은 μ‹μ˜ ꡬ쑰λ₯Ό κ°€μ§€κ³ μžˆκ³ , λ¬Έμ œμ— νžŒνŠΈμ— λ‚˜μ™€μžˆλŠ” κ²ƒμ²˜λŸΌ (μ•ŒνŒŒλ²³ 숫자) * (31 * μ•ŒνŒŒλ²³μœ„μΉ˜) μ‹μ˜ 점화식을 μ‚¬μš©ν•˜λ©΄ λœλ‹€.
ν•΄λ‹Ή λ¬Έμ œμ— 경우 smallκ³Ό large둜 λ‚˜λˆ„μ–΄μ ΈμžˆλŠ”λ° large에 κ²½μš°μ—λŠ” μˆ«μžκ°€ λ„ˆλ¬΄ 컀지가 λ˜λ‹ˆ μˆ«μžκ°€ m (1234567891) 보닀 μ»€μ§€κ²Œ 되면 % m 의 식을 μ „κ°œν•˜λ©΄ λœλ‹€.

pow 에 κ²½μš°μ—λŠ” μ†Œμˆ˜μ  연산을 ν¬ν•¨ν•˜μ—¬ μ •ν™•ν•œ μ •μˆ˜κ°€ 보μž₯λ˜μ§€μ•ŠκΈ°λ–„λ¬Έμ— 반볡적으둜 31을 κ³±ν•˜λŠ” λͺ¨λ“ˆλŸ¬ μ—°μ‚° 방식을 μ‚¬μš©ν•΄μ•Όν•œλ‹€.

code

#include <iostream>
#include <string>

using namespace std;

int main() {
    int n;
    long long sum = 0;
    long long M = 1234567891;
    long long r = 1;

    string l;
    cin >> n >> l;

    for (int i = 0; i < l.size(); i++) {
        int a = (l[i] - 'a' + 1);
        sum = (sum + (a * r) % M) % M;
        r = (r * 31) % M;
    }

    cout << sum << endl;
    return 0;
}

 

ν›„κΈ°

pow ν•¨μˆ˜μ— λŒ€ν•œ μ •ν™•ν•œ 이해λ₯Ό κ°€μ§€κ³ μžˆμ§€μ•Šμ•„ 괜히 고생을 ν•˜μ˜€λ‹€.