Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Общие вопросы по программированию, компьютерный форум
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.06.2010, 10:51   #1
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию Оптимальный поиск и сравнение строк

Имеется динамический массив не сортированных строк (их расположение имеет значение), строки длинные, их содержание и количество не важно и будут меняться. Собственно нужна скорость. Пишу на Дельфи, но меня прежде всего интересует алгоритм, поэтому пишу здесь. Какие будут варианты? Я сам думаю брать первый символ строки и искать сначала по нему, а уж потом проводить полное сравнение. Можно как вариант искать еще и по длине. Скажу сразу длина строк может быть любая и нуль и мегабайты.
Смысл затеи не добавлять дубликатов - массив должен содержать только уникальные строки.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 30.06.2010, 11:04   #2
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию

Идея с первым символом хорошая, но все это будет остаточно долго - необходимо ннайти оптимальное количество символов по которым будет проходить пошаговый поиск с применением сравнения областей памяти.
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ
Alex Cones вне форума Ответить с цитированием
Старый 30.06.2010, 11:43   #3
VintProg
not
Участник клуба
 
Аватар для VintProg
 
Регистрация: 27.06.2009
Сообщений: 1,399
По умолчанию

Код:
//Функция нечеткого сравнения строк БЕЗ УЧЕТА РЕГИСТРА 

//------------------------------------------------------------------------------

//MaxMatching - максимальная длина подстроки (достаточно 3-4)

//strInputMatching - сравниваемая строка

//strInputStandart - строка-образец

 

// Сравнивание без учета регистра

// if IndistinctMatching(4, "поисковая строка", "оригинальная строка  - эталон") > 40 then ...

type

TRetCount = packed record

   lngSubRows: Word;

   lngCountLike: Word;

end;

 

//------------------------------------------------------------------------------

 

function Matching(StrInputA: WideString;

StrInputB: WideString;

lngLen: Integer): TRetCount;

var

TempRet: TRetCount;

PosStrB: Integer;

PosStrA: Integer;

StrA: WideString;

StrB: WideString;

StrTempA: WideString;

StrTempB: WideString;

begin

StrA := string(StrInputA);

StrB := string(StrInputB);

 

for PosStrA := 1 to Length(strA) - lngLen + 1 do

begin

   StrTempA := System.Copy(strA, PosStrA, lngLen);

 

   PosStrB := 1;

   for PosStrB := 1 to Length(strB) - lngLen + 1 do

   begin

     StrTempB := System.Copy(strB, PosStrB, lngLen);

     if SysUtils.AnsiCompareText(StrTempA, StrTempB) = 0 then

     begin

       Inc(TempRet.lngCountLike);

       break;

     end;

   end;

 

   Inc(TempRet.lngSubRows);

end; // PosStrA

 

Matching.lngCountLike := TempRet.lngCountLike;

Matching.lngSubRows := TempRet.lngSubRows;

end; { function }

 

//------------------------------------------------------------------------------

 

function IndistinctMatching(MaxMatching: Integer;

strInputMatching: WideString;

strInputStandart: WideString): Integer;

var

gret: TRetCount;

tret: TRetCount;

lngCurLen: Integer; //текущая длина подстроки

begin

   //если не передан какой-либо параметр, то выход

if (MaxMatching = 0) or (Length(strInputMatching) = 0) or

   (Length(strInputStandart) = 0) then

begin

   IndistinctMatching := 0;

   exit;

end;

 

gret.lngCountLike := 0;

gret.lngSubRows := 0;

   // Цикл прохода по длине сравниваемой фразы

for lngCurLen := 1 to MaxMatching do

begin

       //Сравниваем строку A со строкой B

   tret := Matching(strInputMatching, strInputStandart, lngCurLen);

   gret.lngCountLike := gret.lngCountLike + tret.lngCountLike;

   gret.lngSubRows := gret.lngSubRows + tret.lngSubRows;

       //Сравниваем строку B со строкой A

   tret := Matching(strInputStandart, strInputMatching, lngCurLen);

   gret.lngCountLike := gret.lngCountLike + tret.lngCountLike;

   gret.lngSubRows := gret.lngSubRows + tret.lngSubRows;

end;

 

if gret.lngSubRows = 0 then

begin

   IndistinctMatching := 0;

   exit;

end;

 

IndistinctMatching := Trunc((gret.lngCountLike / gret.lngSubRows) * 100);

end;
VintProg вне форума Ответить с цитированием
Старый 30.06.2010, 11:54   #4
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

а я бы рекомендовал посмотреть на решение проблемы с другой стороны - никто же не мешает завести динамический массив (или список/коллекцию - не суть важно) с номерами (индексами) строк и отсортировать его по значениям строк.
Тогда в этой структуре достаточно сравнивать соседние элементы (строки с этими индексами).

p.s. Предложенный выше алгоритм - это банальное индексирование данных.

p.p.s. а вообще, решение задачи ОЧЕНЬ сильно зависит от конкретных деталей (могут ли строки добавляться/удаляться, часто ли происходит изменение данных, какие требования к скорости (может банальнейший TSTringList + IndexOf по скорости устроит... ) и т.д. и т.п....
Serge_Bliznykov вне форума Ответить с цитированием
Старый 30.06.2010, 11:59   #5
BARNEY
Участник клуба
 
Регистрация: 23.04.2009
Сообщений: 1,058
По умолчанию

можно попробовать разделить разделись массив скажем на N и в N потоках сравнить.

Или этот масив строк скидывать в БД а там уже оптимальным запросом сравнивать. Сделать поле уникальным и БД сама будет это контролировать.
Если вам человек помог, не стесняйтесь говорить спасибо (весы под аватаром)
BARNEY вне форума Ответить с цитированием
Старый 30.06.2010, 12:54   #6
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
p.p.s. а вообще, решение задачи ОЧЕНЬ сильно зависит от конкретных деталей (могут ли строки добавляться/удаляться, часто ли происходит изменение данных, какие требования к скорости (может банальнейший TSTringList + IndexOf по скорости устроит... ) и т.д. и т.п....
Да, да и да, кроме TStringList'a. Строки могут и будут меняться, добавляться (планирую добавление в конец массива), удаляться и т.д. Именно поэтому сортировка не нравиться. Предполагаются активные изменения строк. Это будет что-то вроде умных указателей. Сам массив часть одной структуры, в которой чтобы не повторяться вместо строк будут храниться их индексы в данном массиве. Предполагается, что в данной структуре будут активные перемещения строк.

VintProg, я думаю мой вариант быстрей.

Цитата:
можно попробовать разделить разделись массив скажем на N и в N потоках сравнить.
Потоки не настоящий параллелизм. ИМХО, выгодно использовать для задач когда нужно выполнять разнотипные действия. В данном случае, скорость может быть даже ниже.

Насчет БД - это уже излишество. Задача сводиться к созданию определенной универсальной структуры данных. А если она еще и БД требовать начнет... Это не по-фень-шую.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика

Последний раз редактировалось Utkin; 30.06.2010 в 12:58.
Utkin вне форума Ответить с цитированием
Старый 30.06.2010, 13:24   #7
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

для начала строки какие?
Null Terminated или Lengthed?(или гибрид, как(вроде б) string)
если второе или третье то можно сначало длину сравнить, ну а затем POS проще будет я думаю(хотя на асме можно ускорить это...scasb/w(смотря какие строки))
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 30.06.2010, 13:32   #8
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

До 4-х гигабайт . Длинные.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 30.06.2010, 13:32   #9
VintProg
not
Участник клуба
 
Аватар для VintProg
 
Регистрация: 27.06.2009
Сообщений: 1,399
По умолчанию

А размеры образца и самого текста могут отличатся???
VintProg вне форума Ответить с цитированием
Старый 30.06.2010, 13:35   #10
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Цитата:
Сообщение от VintProg Посмотреть сообщение
А размеры образца и самого текста могут отличатся???
Да. В массиве могут храниться любые строки, включая пустую. Мне нужно поместить в этот же массив еще одну строку (тоже произвольную), но при условии, чтобы она уже не была добавлена в массив. Далее строки за ненадобностью будут удаляться из массива (из любого места). Далее строка может быть изменена (и нет никаких правил их изменения).
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Сравнение строк Jasper92 Общие вопросы C/C++ 6 23.12.2009 12:49
сравнение строк -? Evgenii Общие вопросы Delphi 10 15.07.2009 15:28
С++. Сравнение строк maxlav Помощь студентам 8 25.06.2009 04:33
Сравнение строк Elm0 Паскаль, Turbo Pascal, PascalABC.NET 2 02.06.2008 09:31
Сравнение строк HOMER Общие вопросы Delphi 7 04.01.2008 05:53