2016-02-17 3 views
2

enter image description hereJava: KMP согласовани алгоритм

Я пытаюсь реализовать выше алгоритм в Java. Однако я получаю исключение из-за пределов, и я не знаю, как это исправить.

Я просто переводил psuedocode довольно много строк за строкой.

Вот код:

public static int[] computePrefixFunction(String input) 
    { 
     int[] pi = new int[input.length()]; 
     int k = 0; 
     for (int q = 1; q < input.length(); q++) { 
      char target = input.charAt(q); 
     while (k > 0 && input.charAt(k) != target) k = pi[k - 1]; 
     if (input.charAt(k) == target) k++; 
     pi[q] = k; 
    } 
    return pi; 
} 

public static Queue<Integer> KMPMatcher(String T, String P) 
{ 
    int n = T.length(); 
    int m = P.length(); 
    int[] pi = computePrefixFunction(P); 
    int q = 0; 
    Queue<Integer> Q = new LinkedList<>(); 
    for(int i = 0; i < n; i++) 
    { 
     while(q > 0 && P.charAt(q+1) != T.charAt(i)) 
      q = pi[q]; 
     if(P.charAt(q+1) == T.charAt(i)) 
      q = q + 1; 
     if(q == m-1) // you match it when q reaches size of pattern -1. :) 
     { 
      Q.add(i-m+1); // Change it as well. 
      q = pi[q]; 
     }  
    } 
    return Q; 
} 

public static void main(String[] args) { 
    System.out.println(KMPMatcher("bdacabdacb","bda")); 
} 

Edit: Я обновил код с реализацией Piyush ниже которого скорректированное некоторые из моих проблем. Однако есть и другая проблема.

Я испытал KMPMatcher используя эти:

1) System.out.println(KMPMatcher("bacabab","bab")); // returned [2,4]

2) System.out.println(KMPMatcher("bdacabdacb","bab")); // returned [3]

номер 1 должен возвращать только 4 и номер 2 должен возвращать только пустой список. Почему это происходит? Я пытаюсь нарисовать след с этими входами и сравнить его с psuedocode. Я думаю, что это связано с индексацией в if(q==m-1) (потому что это не сравнение правильной вещи по сравнению с версией psuedocode?), И я не уверен, как ее исправить. Любая помощь, пожалуйста?

+0

функция префикса верна, я ее протестировал и возвращает ожидаемое. Только метод KMPMatcher имеет ошибку – karambit

+0

Было бы очень полезно, если бы вы могли сообщить нам, в какой строке происходит Исключение. – StephaneM

+0

@StephaneM жаль, что я обновил его сейчас – karambit

ответ

3

Проблема в заявке if. Это не должно быть if (q == m-1).

public static int[] computePrefixFunction(String input) 
    { 
     int[] pi = new int[input.length()]; 
     int k = 0; 
     for (int q = 1; q < input.length(); q++) { 
      char target = input.charAt(q); 
     while (k > 0 && input.charAt(k) != target) k = pi[k - 1]; 
     if (input.charAt(k) == target) k++; 
     pi[q] = k; 
    } 
    return pi; 
} 

    public static Queue<Integer> KMPMatcher(String T, String P) 
{ 
    int n = T.length(); 
    int m = P.length(); 
    int[] pi = computePrefixFunction(P); 
    int q = 0; 
    Queue<Integer> Q = new LinkedList<>(); 
    for(int i = 0; i < n; i++) 
    { 
     while(q > 0 && P.charAt(q) != T.charAt(i)) 
      q = pi[q-1]; 
     if(P.charAt(q) == T.charAt(i)) 
      q++; 
     { 
      Q.add(i-q+1); // Change it. 
      q = pi[q-1]; 
     }  
    } 
    return Q; 
} 

public static void main(String[] args) { 
    System.out.println(KMPMatcher("bdacabdacb","bda")); 
} 
+0

нет ли что-то не так с этим решением? Он возвращает [-1,4], но он должен быть [1,5] – karambit

+0

, он возвращает [0,5], и это правильно. – piyush121

+0

Я нашел некоторые проблемы с вашим помощником KMP: со строкой «bacababa» и шаблоном «bab он возвращает [2,4], но 2 не должен в итоге. И со строкой« bdacabdacb »и паттерном« bab »он возвращает [3 ], что неверно. Почему это так? – karambit