Модераторы: korob2001, ginnie

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Алгоритм поиска, Эффективный алгоритм поиска 
:(
    Опции темы
zuk
Дата 20.3.2007, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 6.12.2006

Репутация: нет
Всего: нет



Доброго времени суток.

Если кто сталкивался, дайте совет.
Есть задача: найти наибольшее последовательное совпадение знаков (цифр) строки со знаками (цифрами) других строк. Например, есть файл в формате .dbf, в котором очень!!! много строк содержащих цифры (до 11 цифр в каждой строке (но заранее не известно сколько).  И есть шаблон из определенного кол-ва цифр. Надо найти в файле строку, кот наиболее совпадала бы с шаблоном.

Пр.

шаблон 111111987

строки в файле
......
112434
123424
111123
111111   здесь наибольшее совпадение
111211
...........

а может быть и так

...........
111198
111217
234
342455657
3434
1111112
1111118
11111197
11111198  здесь наибольшее совпадение
232
344
...........

Строки в файле НЕ упорядочены. Повторяю, в файле очень!!! много строк (поэтому возникает еще один вопрос, эффективна ли перед поиском сортировка, ведь она тоже займет время). Нужен наиболее быстрый алгоритм поиска.
PM MAIL   Вверх
Nab
Дата 20.3.2007, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



если именно такова задача, то сортировка поможет однозначно раз, и алгоритм без сортировки, приблизительно такой:
Код

# считываем данные
my @array = <file>;
# счетчик строк
my $i = 0;
# шаблон
my $pattern = 111111987;
# результат
my ($len, $idx) = (0, -1);


foreach (@array) {
  # Ищем не шаблон внутри строк а строки внутри шаблона
  #  сохраняем и длину и номер строки в которой было совпадение 
  # если мы нашли в шаблоне одну из строк и она длиннее предыдущего совпадения
  if ($pattern =~ /$_/ and length > $len) {
    $len = length;
    $idx = $i ;
  }
  $i++
}

print "Наибольшее совпадение в ".$idx." строке ".$array[$idx] if $idx >= 0;


писал прям в форум так что за опечатки не взыщите..


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
zuk
Дата 20.3.2007, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 6.12.2006

Репутация: нет
Всего: нет



Благодарю, но является ли это наиболее эффективным алгоритмом. Здесь идет простая переборка всего файла. Сортировку массива, я думаю можно осущесвить средствами foxpro. Но это надо будет делать через интерфейс на perl. Кстати, может кто посоветовать подходящий модуль для работы с foxpro. Почему нужна эффективность и скорость, кол-во строк может превышть десятки и сотни тысяч. Для начала, я как понимаю их надо выгрузить все в массив, а потом вести поиск.
PM MAIL   Вверх
Nab
Дата 20.3.2007, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



zuk, издеваетесь?
нафига Вам тогда вообще перл?
Вы представляете какие комуникационные требования должны быть? Объемы необходимой памяти скорее всего утрояться а скорость упадет вдвое, по сравнению с тем что вы искали бы одним из продуктов.... 
А вообщето в Perl есть все что необходимо для такой работы...

Алгоритм же я указал, что просто линейный, по отсортированному массиву искать совсем по другому надо. Но отсортированный массив, все одно потребует минимум единичного прохода по всему массиву. Его изначально нужно привести в упорядоченный вид. 
Если же вы собрались сортировать при каждом акте поиска, то это еще вдвое-втрое увеличит необходимость в ресурсах, как памяти так и времени... так что уж лучше линейным поиском. 
Так вот алгоритм которым нужно будет искать зависит именно от того как он будет отсортирован, простым списком, или индексами в dbf, или еще как... может средствами модуля XBase это можно сделать...


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
zuk
Дата 20.3.2007, 17:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 6.12.2006

Репутация: нет
Всего: нет



Я не издеваюсь, Nab. Просто задача только поиском не ограничена. Там нужно будет сделать еще кое-какую работу. Можно, конечно, запрограммировать все это средствами foxpro, но мне показалось, что perl будет удобнее. Ваше мнени, что для такого объема информации perl лучше не использовать? С Гигобайтом памят, сколько примерно займет времени на поиск в файле с 30 тысячами строк (максимально)?
PM MAIL   Вверх
Nab
Дата 20.3.2007, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Я вам не предлагаю реализовывать на foxpro, я вам предлагаю не мешать оба продукта, а выбрать из них что-то одно, иначе вы врядли получите какой либо выиграш ...

Ну 30 тысяч, это не так уж и много smile по скорости конкретно даже представить не могу. Я не знаю скоростных параметров модуля XBase в перле, и не знаю на сколько потолстел Foxpro после нашего последнего общения с ним. Также это зависит от общей структуры данных в dbf, от индексации... не думаю что там только одно поле с такими данными...







--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
zuk
Дата 20.3.2007, 18:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 6.12.2006

Репутация: нет
Всего: нет



Я не хочу мешать и то и другое, я хочу все реализовать на perl. Просто файл в формате dbf. Так значит все таки perl хорошее для этого орудие? Я в нем не сомневался smile . И наиболее эффективным способом Вы счиатете переборку значений, пока не будет найдено совпадение?
PM MAIL   Вверх
nitr
Дата 20.3.2007, 22:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



zuk, с FoxPro-таблицами прекрасно работает как Delphi, C++, Perl и многие другие, думаю у вас Винда, значит поставить драйвер ODBC для оного smile и будет прекрасная поддержка, выбирать язык... Можно выбирать данные из таблиц (а dbf ни что иное smile ) с помощью небезызвестного SQL, простыми запросами ;)

Зачем обрабатывать dbf иначе? Можно ли эту ситуацию "в студию" smile
Незнание FoxPro или его отсутствие или что-то другое, не проблема smile

Perl... "я огромный его поклонник", но что-то невижу +ов ;) особенно если будет и некая "клиентская часть". Да понимаю можно реализовать веб-интерфейс, но многи понравиться? smile

Это сообщение отредактировал(а) nitr - 20.3.2007, 22:39


--------------------
PM   Вверх
amg
Дата 21.3.2007, 08:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



zuk, вот такой простейший линейный алгоритм работает, как мне кажется, достаточно быстро. Проверял на файле из 100_000 ~ 15-значных чисел, созданном такой командой:
Код

perl -le 'print rand for 1..1e5' | sed 's/^0\.//' > file

Скрипт тратит на обработку массива 0.2-0.3 с. На более коротких файлах/строках будет, разумеется, быстрее. Кстати, на сортировку такого массива уходит больше времени (а сортировка в Perl весьма эффективна). Так что, наверное, сортировать не стоит.
Код

open F, 'file' or die;
@a = <F>; chomp @a;
$pattern = reverse '12345678';

$i = $max_count = $max_i = 0;
$max_str = '';
foreach (@a) {
  $pat = $pattern;
  $str = reverse $_;
  $i++;
  $count = 0;
  $count++ while ($pat && $str && chop($pat) eq chop($str));
  if ($count > $max_count) {
    $max_count = $count;
    $max_i = $i;
    $max_str = $_;
  }
}
close F;
print "$max_str $max_i $max_count\n";

Использовал связку reverse-chop: здесь где-то есть пост, в котором выяснили, что это быстрейший способ последовательного получения символов строки.
Если есть опасение, что файл не будет влазить в память, то можно foreach (@a) {} заменить на while (<F>) {}, суммарное время (с учетом зачитывания файла в массив) будет даже меньше.

Это сообщение отредактировал(а) amg - 21.3.2007, 08:38
PM MAIL   Вверх
nitr
Дата 21.3.2007, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



Для работы с табличками FoxPro примерчик даю:
Код

#!perl
use strict; use warnings;
use DBI;
use CGI::Carp qw(fatalsToBrowser);

my $dsn = 'DRIVER=Microsoft FoxPro VFP Driver (*.dbf);UID=;Deleted=Yes;Null=Yes;Collate=Machine;BackgroundFetch=Yes;Exclusive=No;SourceType=DBF;SourceDB=D:\DBF'; #Указываем каталог D:\DBF , где лежат наши таблички,-файлы dbf

my $dbh = DBI->connect("dbi:ODBC:$dsn", '', '', { PrintError => 1, RaiseError => 1 } );

my $sth = $dbh->prepare('SELECT * FROM `FILENAME.DBF`'); #Указывать .DBF необязательно
$sth->execute;
while (my $row = $sth->fetchrow_arrayref) {
    print join("\t", @$row)."\n";
}

а вот сами драйвера тут - http://msdn2.microsoft.com/en-us/vfoxpro/bb190233.aspx

Добавлено @ 11:32 
З.Ы.: и почему-то на Делфи работало быстрее ;) хе хе, или у меня таблицы большие ;), zuk не ответил о клиентской части, если конечно он просто тренируется, типа обучается перлу, то другое, а если это работа, то мой совет был уже дан не в пользу перла :(

Добавлено @ 11:35 
Но у меня работа с ODBC...


--------------------
PM   Вверх
nitr
Дата 21.3.2007, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



Проверил с модулем DBD::XBase:
Код

#!perl
use strict; use warnings;
use DBI;

my $dbh = DBI->connect('dbi:XBase:.', '', '', { PrintError => 1, RaiseError => 1 } ) or die $DBI::errstr;

my $sth = $dbh->prepare('SELECT * FROM R050506.DBF') or die $dbh->errstr();
$sth->execute;
while (my $row = $sth->fetchrow_arrayref) {
    print join("\t", @$row)."\n";
}

тот же результат по времени smile

Добавлено @ 11:58 
Разница двух методов:
1 - выдаёт в виндовой кодировке cp1251
2 - в кодировке таблицы, в моём случае cp866


--------------------
PM   Вверх
nitr
Дата 21.3.2007, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



Второй всё же быстрее, даже если перекодировку сделать в другую... smile Но всё же медленее Delphi+ADO.
XBase подходит особенно для *nix smile , так что если требуется сделать на перл работу с dbf, используй этот Драйвер DBD::XBase

Это сообщение отредактировал(а) nitr - 21.3.2007, 12:06


--------------------
PM   Вверх
zuk
Дата 21.3.2007, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 6.12.2006

Репутация: нет
Всего: нет



Добрый вечер.

Это для работы. GUI (если это подразумевалось под клиентсокй частью), в принципе, не самое важное. Если надо, простейший интерфейс можно реализовать на Tk.

Суть задачи после поиска. Найдя соответсвие, вычисляем разницу в кол-ве знаков. Далее, раскрываем число (добавляем к найденному цифры), но при этом на минимальное кол-во знаков. Вобщем пример.

111111789 - шаблон

111111 - найденное

надо

1111110
1111111
1111112
1111113
1111114
1111115
1111116
11111170
11111171
11111172
...............
111111780
111111781
111111782
111111283
.................
111111789 - здесь надо добавить строку в другое поле таблицы (но это можно реализоваь в любом месте)
11111179 
1111118
1111119

Теперь стало яснее. Таблица состоит из нескольких столбцов. Но поиск придется вести по одному (о кот и идет речь). Я думаю перебирать значение в нем, например, fetch_arrow и сравнивать. Выгружать все в массив я думаю нет смысла. Так реализовать поиск. Использовать модуль xbase. ОС Винда. Конечный файл должен быть преобразованный начальный, то есть тоже dbf. 

Завтра выложу то,что получилось.
Спасибо за участие))
PM MAIL   Вверх
nitr
Дата 21.3.2007, 22:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



Цитата(zuk @  21.3.2007,  17:40 Найти цитируемый пост)
Выгружать все в массив я думаю нет смысла. Так реализовать поиск.

где ты в моём примере нашёл это? smile это раз, а два - реализовать проще с DBI-DBD::XBase-запросами SQL. Данный модуль вообще не зависит от ОС.

А как работать с файлом dbf иначе... имхо чушь ;)


--------------------
PM   Вверх
tishaishii
Дата 23.3.2007, 21:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Создатель
***


Профиль
Группа: Завсегдатай
Сообщений: 1262
Регистрация: 14.2.2006
Где: Москва

Репутация: 4
Всего: 8



Посмотри модуль String::Approx.
PM MAIL ICQ Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0913 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.