Поиск подстроки в строке

Тема в разделе "WASM.A&O", создана пользователем JCronuz, 27 ноя 2009.

  1. JCronuz

    JCronuz New Member

    Публикаций:
    0
    Регистрация:
    26 сен 2007
    Сообщения:
    1.240
    Адрес:
    Russia
    Добрый вечер.

    Какой самый оптимальный вариант по скорости/размеру Вы знаете?
    Написал свой вариант, но мне кажется что, он не самый оптимальный и есть во много раз лучше. Хотелось бы увидеть Ваши варианты.

    Примечание #1:
    Поиск по форуму, на момент создания темы не работал.

    Примечание #2:
    Собственный вариант представлю чуть позже.
     
  2. JCronuz

    JCronuz New Member

    Публикаций:
    0
    Регистрация:
    26 сен 2007
    Сообщения:
    1.240
    Адрес:
    Russia
    Блин, походу создания мною был создан вирус, нод32 - "new_heur virus"
     
  3. Proteus

    Proteus Member

    Публикаций:
    0
    Регистрация:
    19 июн 2004
    Сообщения:
    344
    Адрес:
    Russia
    Про поиск можно книгу, килограм в 10 написать. Всё от конкретных задач, образцов и текстов зависит.

    А образно говоря, оптимальный вариант, как раз постом ниже обсуждали... Правда напрямую про это не говорили
     
  4. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    вот тут некоторые товарищи советовали буку
    дэн гасфилд "строки, деревья и последовательности в алгоритмах"
    всего 658 страничек
     
  5. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    2010_07_14

    Сильно ее не тестировал.
    В отличии от предыдущих моих попыток, должна работать нормально.
    |_через полгода скажу, что ни одного жука не увидел.

    Код (Text):
    1. Итак. Процедура ищет вхождение подстроки в строку.
    2. str   = искомое
    3. lstr  = длина искомого
    4. src   = тут будем искать
    5. lsrc  = длина рабочего потока
    6. start = старт с 1 относительно головы src(DF=0) или хвоста(DF=1)
    7. wall  = стоп с 1 относительно головы src(DF=0) или хвоста(DF=1)
    8.         работа продолжается по данную позицию
    9. eax   <- результат, приведенный к DF=0


    I've not tested it much. Still it does good unlike the one before.

    Код (Text):
    1. ; Searches for a byte pattern in another one. Count from 1.
    2. ; result <- eax.
    3. ; restore: eflags.
    4. ; Both search directions supported but result is always given as if eflags.df=0.
    5. ; -str   = wanted.
    6. ; -lstr  = length of str in bytes.
    7. ; -src   = source.
    8. ; -lsrc  = length of src in bytes.
    9. ; -start = job start relatively src's head(eflags.df=0) or tail(eflags.df=1).
    10. ; -stop  = job end(wall) relatively src's head(eflags.df=0) or tail(eflags.df=1).
    11. dbgstr pos
    12. proc pos uses ebx ecx edx esi edi, str:dword, lstr:dword, src:dword, lsrc:dword, start:dword, stop:dword
    13.         pushfd
    14.         xor     eax,eax        ; result=0
    15.  
    16.         cdq
    17.         or      edx,[lstr]
    18.         jz      .exit          ; length(str)=0
    19.  
    20.         mov     ecx,eax
    21.         or      ecx,[lsrc]
    22.         jz      .exit          ; length(src)=0
    23.  
    24.         cmp     edx,ecx
    25.         ja      .exit          ; length(str)>length(src)
    26.  
    27.         mov     ebx,eax
    28.         or      ebx,[start]
    29.         jz      .exit          ; start=0
    30.         cmp     ebx,ecx
    31.         ja      .exit          ; start>length(src)
    32.  
    33.         mov     esi,eax
    34.         or      esi,[stop]
    35.         jz      @f             ; stop=0
    36.         cmp     esi,ecx
    37.         ja      @f             ; stop>length(src) -> stop=0
    38.         cmp     esi,ebx
    39.         jbe     .exit          ; start>=stop
    40.         lea     ecx,[esi-1]    ; ecx>0 <- const
    41.  
    42. @@:     dec     ebx
    43.         sub     ecx,ebx        ; ecx>0 <- const
    44.  
    45.         dec     edx            ; cmpsb.ecx
    46.         sub     ecx,edx        ; scasb.ecx
    47.         jbe     .exit          ; over(src)flow
    48.  
    49.         bt      dword[esp],10
    50.         mov     esi,[str]
    51.         mov     edi,[src]
    52.         lea     eax,[edi+ebx]
    53.         cmovnc  edi,eax
    54.         jnc     @f             ; search TO bigger address
    55.         neg     ebx
    56.         add     ebx,[lsrc]
    57.         lea     edi,[edi+ebx-1]
    58.         add     esi,edx        ; search FROM bigger address
    59. @@:     lodsb
    60.  
    61. @@:     repne   scasb
    62.         jne     .fail          ; no str[1] in src
    63.         test    edx,edx
    64.         jz      @f             ; length(str)=1 -> no need to check the rest(edx)
    65.         push    esi edi
    66.         mov     ebx,ecx
    67.         mov     ecx,edx
    68.         repe    cmpsb
    69.         pop     edi esi
    70.         je      @f             ; str rest(edx) match
    71.         mov     ecx,ebx
    72.         jecxz   .fail
    73.         jmp     @b
    74.  
    75. @@:     bt      dword[esp],10
    76.         jnc     @f
    77.         neg     edx
    78.         lea     edi,[edi+2+edx]; switch result to be always src's head relative
    79. @@:     sub     edi,[src]
    80.         mov     eax,edi
    81.         jmp     .exit
    82.  
    83. .fail:  xor     eax,eax
    84.  
    85. .exit:  popfd
    86.         ret
    87. endp
     
  6. luckysundog

    luckysundog New Member

    Публикаций:
    0
    Регистрация:
    28 окт 2008
    Сообщения:
    106
    самым распространенным наверно будет алгоритм Бойера-Мура.
    хотя мне вот интересно, что в известных текстовых редакторах используется.
     
  7. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Самым распространенным будет repne scasb+repe cmpsb в цикле.
     
  8. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    KeSqueer
    Нет, это не все варианты ловит. Собственно, почему и выдумали Бойера-Мура.
     
  9. luckysundog

    luckysundog New Member

    Публикаций:
    0
    Регистрация:
    28 окт 2008
    Сообщения:
    106
    спешу обрадовать - в алгоритме Бойера-Мура тоже можно применить ваши любимые repne scasb+repe cmpsb ;)
     
  10. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Ustus
    Приведите пример, где repne scasb+repe cmpsb в цикле будет ловить не все варианты.
     
  11. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    2010_07_14

    интерактивность с пользовательской стороной

    Interactivity :)
     
  12. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    edemko
    Янепонимать.
     
  13. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    Ustus
    В отличии от scasb, где строка сканируется по-байтно, Бойер-Мур сканирует строку кусками, равными по длине подстроки -- выигрыш в скорости, а так полностью согласен с KeSqueer комбинация "repne scasb+repe cmpsb" в цикле выловит все возможные варианты
     
  14. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    2010_07_14

    таким образом callBack делает, чего ей хочется


    ...
    .if [callBack]<>0
    call [callBack] ; thus callBack-the proc can do all ever
    .end if
    ...
     
  15. luckysundog

    luckysundog New Member

    Публикаций:
    0
    Регистрация:
    28 окт 2008
    Сообщения:
    106
    недавно написал алгоритм Бойера-Мура-Хорспула (упрощенный вариант Бойера-Мура без суффиксной эвристики).

    кому интересно, можете заоптимизировать. например, как max7C4 в соседней теме оптимизировал примитивный алгоритм поиска подстроки http://wasm.ru/forum/viewtopic.php?id=36135

    Код (Text):
    1. int substr_horspool(char* haystack, char* needle)
    2. {
    3.     int i,j,k;
    4.     int Lh = strlen(haystack);
    5.     int Ln = strlen(needle);
    6.     int T[256];
    7.    
    8.     for(i=0; i<256; ++i) T[i] = Ln;
    9.     for(i=0; i<Ln-1; ++i)
    10.     {
    11.         k = (unsigned char)needle[i];
    12.         T[k] = Ln-i-1;
    13.     }
    14.    
    15.     for(i=Ln-1; i<Lh; (k==Ln-1) ? i+=T[(unsigned char)haystack[i]] : ++i)
    16.     {
    17.         for(j=i,k=Ln-1; k>=0; --j,--k)
    18.         {
    19.             if(haystack[j] != needle[k]) break;
    20.         }
    21.         if(k<0) break;
    22.     }
    23.    
    24.     return (k<0) ? i-Ln+1 : -1;
    25. }
     
  16. S_Alex

    S_Alex Alex

    Публикаций:
    0
    Регистрация:
    27 авг 2004
    Сообщения:
    561
    Адрес:
    Ukraine
    Вот СкопиПастил со своего проекта (немного упростил). Надеюсь работает.
    Код (Text):
    1. ;edi - адрес начала строки в которой ищем
    2. ;edx - длина строки в которой ищем
    3.  
    4. ;szHL - адрес начала строки для поиска в сегменте .data
    5. ;[sizeHL] - длина строки для поиска
    6.  
    7. .while edx>0
    8.     mov     ecx,    [sizeHL]
    9.     xor     eax,eax
    10.     .while  ecx
    11.         xor     al, [edi+ecx-1] ;
    12.         xor     al, [szHL+ecx-1]
    13.         or      ah, al
    14.         dec     ecx
    15.     .endw
    16.     .if ah==0
    17.         ; строка найдена
    18.     .endif
    19.     dec edx
    20. .endw
     
  17. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    KeSqueer
    Э... возможно, я неправильно понял, как именно scasb+repe cmpsb... Может если увижу живой код, станет легче?

    Mikl___
    Ну, не совсем так... преимущество Бойера-Мура в том, что он однопроходный, а при тупом сканировании придется делать откат. А сканировать все равно придется байтами, как же иначе??? (я не беру на рассмотрение всякие полухакерские ускорения :) )
     
  18. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    Код (Text):
    1. repne scasd
    :)z
     
  19. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    edemko
    Не совсем, но близко :) Идею имел ввиду именно такую - работать в 32 разряда. Только вот Бойера-Мура в такой оптимизации сходу замутить - нужен талант Большого Темного Зеркала :) мне так вот сходу слабо :)
    А еще строковые операции - тот еще тормоз, лучше через mov.
     
  20. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    Код (Text):
    1. mov     eax,[esi] ;?
    2. lodsd                ;?