2013-04-16 2 views
4

Я искал подход сделать массив суффиксов на Java.
Я нашел два варианта возможностей. Более того, я хочу гораздо глубже понять различия между этими вариантами.
Включает running time & space.Как эффективно формировать массив суффиксов?

Код (суффиксы):

public static String[] suffixes(String s) 
{ 
int N = s.length(); 
String[] suffixes = new String[N]; 
for (int i = 0; i < N; i++) 
suffixes[i] = s.substring(i, N); 
return suffixes; 
} 

Код (StringBuilder суффиксы):

public static String[] suffixes(String s) 
{ 
int N = s.length(); 
StringBuilder sb = new StringBuilder(s); 
String[] suffixes = new String[N]; 
for (int i = 0; i < N; i++) 
suffixes[i] = sb.substring(i, N); 
return suffixes; 
} 

Вопрос:

  • Как эффективно формировать А.Р. луч суффиксов?
+0

Использование версии StringBuilder не улучшит производительность подстроки. Это почти такая же функция в любом случае. (На самом деле, в старых версиях Java, использующих StringBuilder, на самом деле может быть немного медленнее, не считая накладных расходов на создание самого объекта StringBuilder.) –

+1

У первого фрагмента есть «линейное время и линейное пространство». И второй фрагмент имеет «квадратичное время и квадратичное пространство» –

ответ

3

Там не будет никакой заметной разницы между этими двумя способами это делать, что вы описываете: так String s в Java являются непреложный, новый объект будет создан для каждого суффикса. Создание подстроки из String против StringBuilder не даст вам большой разницы в производительности по сравнению с распределениями и копированием, необходимыми для создания новых строковых объектов.

Когда вы ищете суффикс, передавая конечный индекс не является необходимым: использовать перегрузку, которая принимает один int вместо:

for (int i = 0; i < N; i++) 
    suffixes[i] = s.substring(i); 
+0

В более старых версиях Java 'String.substring' иногда реализуется совместное использование массива' char [] 'исходной строки (против создания нового), с другим смещения и длины. Поскольку StringBuilder изменен, это не может быть сделано для версии StringBuilder подстроки, что делает ее несколько более медленной. Однако вся схема общих массивов символов в основном была оставлена ​​в новых версиях Java. –

0

Единственное различие между вашими фрагментами кода использует строку или StringBuilder, также вы используете его только для извлечения подстроки.
subString() из StringBuilder делает

new String(offset + beginIndex, endIndex - beginIndex, value); 

и subString() из строки делает

new String(offset + beginIndex, endIndex - beginIndex, value); 

оба же и создает новую строку, так что привычка быть какая-то разница в производительности

0

Наиболее эффективным способом было бы для использования массива char. Однако это не будет столь значительным, как самая дорогостоящая операция по созданию объектов String.

String s = "foobarbaz"; 
char[] cha = s.toCharArray(); 
int length = cha.length; 
String[] suffixes = new String[length]; 
for (int i = 0; i < length; ++i) 
    suffixes[i] = new String(cha, i, length-i); 
0

Вы можете сделать это, что позволяет избежать метод подстроки,

public String[] suffix(String s) 
{ 
    String[] suffixes = new String[s.length()]; 
    String suffix = null; 
    for (int i = 0 ; i < s.length() ; i++) 
    { 
     suffix = suffix == null ? "" + s.charAt(i) : suffix + s.charAt(i); 
     suffixes[i] = suffix; 
    } 

    return suffixes; 
} 

не уверен, если это быстрее, хотя.

+0

Ничего, это не совсем то, что нужно! –

+0

Ваш комментарий означает, что эта работа не так? –

+0

Это фактически вычисляет префиксы, а не суффиксы, я думал, что оставил бы ответ здесь, потому что OP мог бы найти его полезным, но я могу удалить его, если вы пожелаете. –

0

В конце вам всегда требуется строка n + 1 для выполнения этой задачи. Единственное, что можно оптимизировать, - это время создания этих объектов.

Вы можете создать строковое представление в виде массива символов и ленивый (по запросу) возврат суффиксов.

Вы можете использовать интерфейсы итерации и Iterator, чтобы сделать это:

public class StringSufixies implements Iterable<String> { 

    private final String input; 

    public StringSufixies(String input) { 
     this.input = input; 
    } 

    @Override 
    public Iterator<String> iterator() { 
     return new SuffixStringIterator(input); 
    } 

    private static class SuffixStringIterator implements Iterator<String> { 

     private final String input; 
     private final int size; 
     private int suffixId; 

     private SuffixStringIterator(String input) { 
      this.input = input; 
      this.size = input.length(); 
      this.suffixId = 1; 
     } 

     @Override 
     public boolean hasNext() { 
      return suffixId <= size; 
     } 

     @Override 
     public String next() { 
      return input.substring(0, suffixId++); //At this point we create new String 
     } 

     @Override 
     public void remove() { 
      //Add throw or other impl 
     } 

    } 

} 

Вы могли бы реализовать ключевые функции над массивом символов.

private static class SuffixCharIterator implements Iterator<String> { 

private final char[] charSequence; 
private final int size; 
private int suffixId = 0; 

private SuffixCharIterator(char[] charSequence) { 
    this.charSequence = charSequence; 
    this.size = charSequence.length; 
} 

@Override 
public boolean hasNext() { 
    return suffixId <= size; 
} 

@Override 
public String next() { 
    return new String(charSequence, 0, suffixId++); //At this point we create a new String 
} 

@Override 
public void remove() { 

} 

} 

Но ИМХО сложнее, и мы ничего не получаем.

Преимущество этого решения в том, что вы можете работать над результатами и решать, чтобы остановить, прежде чем все префиксы создаются.

Смежные вопросы