얼렁뚱땅 JAVA 알고리즘
[JAVA] Rabin-karp 알고리즘 - 동일 패턴 유무 찾기
MOSTAR
2023. 3. 15. 11:10
가장 쉽게 생각할 수 있는 무지성으로 비교하기
String : ababc
Pattern : abc
Step 1. aba != abc
Step 2. bab != abc
Step 3. abc == abc
Step 3에서 존재한다고 빠르게 파악할 수 있을 것이다.
각 Step에서 사람처럼 한번에 딱 보면 O(1)의 시간이 걸릴 거 같지만, 사실은 아니다
한 str1과 str2를 비교하기 위해서는 한글자 한글자 비교한다.
예를 들어 JAVA의 str1.equals(str2)를 사용한다면(Step 1)
a == a true
b == b true
a != c false
으로 Step 1은 False라고 판단하는 것이다.
다시 말해, 글자 하나하나 보기 때문에 글자가 크거나 하면 시간이 매우 오래 걸린다.
이것을 해결할 수 있는 방법 중 하나는 Rabin-karp 알고리즘이다.
음 ,, 설명을 하려고 했는데 그림이 필요할 거 같고 그럼 그림을 그려야 하는데 조금 귀찮으니까 코드만 올려야겠다 *^^*
Rabin-karp 알고리즘을 이용하면, eqauls 함수처럼 글자 하나하나를 항상 비교하는 것이 아니라
맨 앞에 있는 문자(이제 안 볼 문자)에 해당하는 수치 뺴주고, 3 곱해주고(차수가 하나씩 올라가므로),
새롭게 볼 숫자에 해당하는 수치 더해주는 수치적인 계산이기 때문에 시간 복잡도가 높지 않다.
Rabin-karp : O(N+M)
Broth-force : O(MN)
public class rabin_karp {
public static void r_k(String str, String pattern) {
int answer = 0;
int pat = 0;
for(int i=0;i<pattern.length();i++) {
answer += (pattern.charAt(i)*Math.pow(3, pattern.length()-i-1));
}
for(int i=0;i<str.length()-pattern.length()+1;i++) {
if(i==0) {
for(int j=0;j<pattern.length();j++) {
pat += str.charAt(j)*Math.pow(3, pattern.length()-j-1);
}
}
else {
pat -= str.charAt(i-1)*Math.pow(3, pattern.length()-1);
pat = pat * 3;
pat += str.charAt(i+2)*Math.pow(3, 0);
}
if(answer==pat && str.substring(i,i+pattern.length()).equals(pattern)) {
System.out.println((i+1)+"번째에서 패턴 등장");
return;
}
}
System.out.println("발견안됨 ");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
String str = "AABCDDAACE";
String pattern = "BCD";
r_k(str,pattern);
}
}