На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Модераторы: Qraizer
Страницы: (3) [1] 2 3  все  ( Перейти к последнему сообщению )  
> Нужен быстрый алгоритм сравнение строк...
    Я делаю так:
    сравниваю побайтово символы строки1 и строки2, если хоть один не совпадает то строки не совпадают...
    Нужно сделать быстрее. Подскажите какие ещё варианты есть?
      Не понимаю, куда такая скорость. Я делал прогу, там надо было не просто сравнивать, а производить поиск сочетаний в вводимом слове. Сочетаний было около 28000, всё должно было обрабатываться в хуке во время печати на клаве. Функции CString действительно тормозили, так как там постоянно память перевыделялась, но Cи Runtime функции справились отлично!
        ИМХО
        Команда ассемблера cmpsb спасет отца русской демократии
          strcmp тоже вроде быстро пашет, всяко быстрее самописного цикла
            2kourov :
            Понимеешь программа должна проанализировать
            сотни тысяч или даже миллионы строк... и побыстрее

            2DemonM :
            В моём случае strcmp не поможет...
              Пишешь примерно следующее (пишу по памяти, поэтому за ошибки не обессудь):
              int len1 = strlen(s1);
              int len2 = strlen(s2);
              if (len1 != len2)
              return false;
              bool ret_val = false;
              _asm
              {
              mov esi, str1
              mov edi, str2
              mov ecx, len1
              rep cmpsb
              jnc exit
              mov ret_val, 1
              exit:
              }
              return ret_val;
              Поиск длины строки тоже можешь завернуть на ассемблере. Если сделаешь функции инлайновыми, то быстрей алгоритма ты не найдешь.
                Кстати, вот пример из CRTL VC++ (файл strncmp из дериктории vc98\crt\src\intel\):
                CODESEG
                public strncmp
                strncmp proc \
                uses edi esi ebx, \
                first:ptr byte, \
                last:ptr byte, \
                count:IWORD

                mov ecx,[count] ; cx=max number of bytes to compare
                jecxz short toend ; it's as if strings are equal
                mov ebx,ecx ; bx saves count
                mov edi,[first] ; di=first pointer (es=segment part)
                mov esi,edi ; si saves first pointer
                xor eax,eax ; ax=0
                repne scasb ; count bytes
                neg ecx ; cx=count - strlen
                add ecx,ebx ; strlen + count - strlen
                okay:
                mov edi,esi ; restore first pointer
                mov esi,[last] ; si = last pointer
                repe cmpsb ; compare strings
                mov al,[esi-1]
                xor ecx,ecx ; set return value = 0
                cmp al,[edi-1] ; last-first
                ja short lastbig ; <last is bigger>
                je short toend ; <equal>
                ;jb short firstbig ; <first is bigger>
                firstbig:
                dec ecx ; first string is bigger
                dec ecx ; make FFFE so 'not' will give 0001
                lastbig: ; last string is bigger
                not ecx ; return -1
                toend:
                mov eax,ecx ; return value
                ret ; _cdecl return
                strncmp endp
                end
                  2Flex Ferrum:
                  К сожалению тут strlen уже всё тромозит...
                  если я поставю хтабы только сравнение на разность строк, даже не сравнивая 2 массива, то это уже дольше работает чем так как я делю(как в самой первой месаге написанно)
                    В той же директории лежит модуль strlen.asm. Объедени это в одну функциию, написанную на асме, или посмотри, как это реализовано в модуле strcmp.asm.
                      Возможно, поможет такая стратегия (я использовал нечто похожее при написании LZ77-сжатия, и это помогло):
                      Сравниваем не a[0]==b[0]; a[1]==b[1]; a[2]==b[2]..., а:
                      L-длинна строки
                      a[0]==b[0]; a[L-1]==b[L-1]; a[1]==b[1]; a[L-2]==b[L-2]; т.е. начинаем сравнивать с начала и конца.
                        int find_str(char* buf1,char* buf2,int len1,int len2)
                        {
                        for(int i=len;i>=0;i--){
                        if(!buf1[i]|buf2[i]){return -1}; //строки не совпадают!
                        };
                        return 0; //строки совпадают
                        };

                        вот как ща сделал...
                        Кто быстрее сам алгоритм может проедложить?(именно алгоритм а не оптимезацию на асме)
                          Может хотел написать вот так:
                          int find_str(char* buf1,char* buf2,int len1,int len2)
                          {
                          for(int i=len;i>=0;i--){
                          if(!(buf1[i]^buf2[i])){return -1}; //строки не совпадают!
                          // вот тут поправил | на ^ и скобоцки расставил
                          };
                          return 0; //строки совпадают
                          };

                          надеюсь, просто пропущен код, который сравнивает len1 и len2,
                          кроме того где-то там же появляется третья переменная len,
                          видимо меньшая из них.
                            2 Sourcer: Тебе Flex Ferrum правильно предложил напишу функцию на ассемблере. На Си ты все равно быстрее не напишешь, какой бы ты алгоритм не придумал. Задача тривиальна, алгоритм один, все зависит от реализации.
                            Предлагаю тебе текст функции и могу заявить, что быстрее реализации ты не придумаешь.
                            __declspec(naked) int find_str(char* buf1, char* buf2, int len1, int len2)
                            {
                            __asm
                            {
                            push esi
                            push edi
                            xor eax,eax
                            mov ecx,len1
                            cmp ecx,len2
                            jne exit1
                            mov esi,s1
                            mov edi,s2
                            mov edx,ecx
                            shr ecx,2
                            jz cmpbytes
                            repe cmpsd
                            jne exit1
                            cmpbytes:
                            mov ecx,edx
                            and ecx,3
                            repe cmpsb
                            jne exit1
                            inc eax
                            exit1:
                            pop edi
                            pop esi
                            ret
                            }
                            }
                            __declspec(naked) не убирай, чтобы компилятор свой пролог и эпилог не вставлял, он тоже может подтармаживать
                              Если строки длинные, возможно быстрее будет использовать не CMPSB, а CMPSD.
                                Sourcer:
                                А что, побитовое OR или XOR работают быстрее обычного стравнения?
                                И еще. Когда тебе нужен действительно быстрый алгоритм - без ручной оптимизации на ассемблере не обойтись - каким бы ни был хорошим компилятор, все равно он не соптимизирует код лучше человека (в некоторых случаях).
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) [1] 2 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0344 ]   [ 16 queries used ]   [ Generated: 27.04.24, 22:47 GMT ]