Deep_Dev

Hashing λΆ€λΆ„ μ„±κ³΅μ„œλΈŒνƒœμŠ€ν¬

 
μ‹œκ°„ μ œν•œλ©”λͺ¨λ¦¬ μ œν•œμ œμΆœμ •λ‹΅λ§žνžŒ μ‚¬λžŒμ •λ‹΅ λΉ„μœ¨
1 초 512 MB 32492 10101 8685 30.995%

문제

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이 λ“€μ–΄μ˜¨λ‹€. λ‘˜μ§Έ μ€„μ—λŠ” 영문 μ†Œλ¬Έμžλ‘œλ§Œ 이루어진 λ¬Έμžμ—΄μ΄ λ“€μ–΄μ˜¨λ‹€.

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

좜λ ₯

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

 

 

 


100점 λ°›κΈ° μœ„ν•΄μ„œλŠ”, 

Math.pow μ‚¬μš© X

Long νƒ€μž… μ‚¬μš© O 쑰건을 λ§žμΆ°μ•Όν•œλ‹€.

 

 

Math.pow μ‚¬μš©ν•œ 50점짜리 μ½”λ“œ

import java.util.*;

class Main {
    public static void main(String args[]) throws Exception {
        Scanner kb = new Scanner(System.in);
        int n=kb.nextInt();
        String s=kb.next();
        String[] arr=s.split("");
        String[] str={"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
        int[] num={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};

        int sum=0;
        int index=0; // 제곱 수

        for(int i=0; i<n; i++){
            for(int j=0; j<str.length; j++){
                if(arr[i].equals(str[j])){
                    sum+=num[j]*(Math.pow(31,index));
                    break;
                }
            }
            index++;
        }
        System.out.println(sum);
    }
}

 

 

 

Longνƒ€μž… + Math.pow μ‚¬μš© μ•ˆν•œ 100점 μ½”λ“œ ( r=31을 λˆ„μ  ν•©μœΌλ‘œ 이용 )

import java.util.*;

class Main {
    public static void main(String args[]) throws Exception {
        Scanner kb = new Scanner(System.in);
        int n=kb.nextInt();
        String s=kb.next();
        long sum=0;
        double r=0;
        r=Math.pow(31,0);
        for(int i=0; i<n; i++ ){
            sum+=(s.charAt(i)-96)*r;
            r=r*31%1234567891;
        }
        System.out.println(sum&1234567891);
    }
}