Высокоэффективный поиск байта [] содержится в другом байте [] [duplicate]

Я отвечу ужасным, нарисованным рукой комиком. Второе изображение является причиной того, что result является undefined в вашем примере кода.

25
задан weston 14 January 2015 в 17:46
поделиться

9 ответов

Строки Java состоят из 16-битных char s, а не 8-битных byte s. A char может содержать byte, поэтому вы всегда можете сделать свои байтовые массивы в строки и использовать indexOf: символы ASCII, управляющие символы и даже нулевые символы будут работать нормально.

Здесь является демо:

byte[] big = new byte[] {1,2,3,0,4,5,6,7,0,8,9,0,0,1,2,3,4};
byte[] small = new byte[] {7,0,8,9,0,0,1};
String bigStr = new String(big, StandardCharsets.UTF_8);
String smallStr = new String(small, StandardCharsets.UTF_8);
System.out.println(bigStr.indexOf(smallStr));

Это печатает 7.

Однако, учитывая, что ваш большой массив может составлять до 10 000 байт, а малый массив - всего десять байт, это решение может быть не самым эффективным по двум причинам:

  • Требуется скопировать ваш большой массив в массив, который в два раза больше (в той же емкости, но с char вместо byte). Это увеличивает ваши потребности в памяти.
  • Строковый алгоритм поиска Java не самый быстрый из доступных. Вы можете получить достаточно быстро, если вы реализуете один из продвинутых алгоритмов, например, Knuth-Morris-Pratt . Это может привести к снижению скорости выполнения в десять раз (длина маленькой строки) и потребует дополнительной памяти, пропорциональной длине маленькой строки, а не большой строке.
4
ответ дан dasblinkenlight 27 August 2018 в 13:23
поделиться
5
ответ дан 18446744073709551615 27 August 2018 в 13:23
поделиться
18
ответ дан ant-depalma 27 August 2018 в 13:23
поделиться
0
ответ дан Benjamin Gillhofer 27 August 2018 в 13:23
поделиться
2
ответ дан BullyWiiPlaza 27 August 2018 в 13:23
поделиться
1
ответ дан Enamul Hassan 27 August 2018 в 13:23
поделиться
6
ответ дан MonoThreaded 27 August 2018 в 13:23
поделиться

Симпольным способом было бы сравнить каждый элемент:

public int indexOf(byte[] outerArray, byte[] smallerArray) {
    for(int i = 0; i < outerArray.length - smallerArray.length+1; ++i) {
        boolean found = true;
        for(int j = 0; j < smallerArray.length; ++j) {
           if (outerArray[i+j] != smallerArray[j]) {
               found = false;
               break;
           }
        }
        if (found) return i;
     }
   return -1;  
}  

Некоторые тесты:

@Test
public void testIndexOf() {
  byte[] outer = {1, 2, 3, 4};
  assertEquals(0, indexOf(outer, new byte[]{1, 2}));
  assertEquals(1, indexOf(outer, new byte[]{2, 3}));
  assertEquals(2, indexOf(outer, new byte[]{3, 4}));
  assertEquals(-1, indexOf(outer, new byte[]{4, 4}));
  assertEquals(-1, indexOf(outer, new byte[]{4, 5}));
  assertEquals(-1, indexOf(outer, new byte[]{4, 5, 6, 7, 8}));
}

По мере обновления вашего вопроса: строки Java - это строки UTF-16, они не заботятся о расширенном наборе ASCII, поэтому вы можете использовать string.indexOf ()

34
ответ дан morpheus05 27 August 2018 в 13:23
поделиться
1
ответ дан riversun 27 August 2018 в 13:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: