Подписка

Проекты

Сборник идей для разработок в Delphi и использования их в Интернет. Участвуй в работе коллективного разума!

Google API в Delphi - проект с открытым исходным кодом.


А тут я коплю на лицензию Delphi 2011. Сумма пожертвования не фиксирована.

Друзья блога

Блоги и сообщества

DelphiFeeds.ru - Все Delphi-блоги Рунета О раскрутке блога по программированию Сообщество умных людей VR-Online.RU Бесплатный журнал для программистов и всех, кто интересуется IT Статьи и уроки по Delphi Статьи по Delphi

Счётчики


Анализ веб сайтов

Рейтинг блогов




Система Orphus

  • 28Jul

    Эта статья будет полезна в первую очередь тем, кто часто имеет дело со сравнением и анализом строковых переменных. Также, думаю, что этот алгоритм смогут использовать в своей работе и люди, занимающиеся парсингом.

    Цель: найти в двух строках самую длинную повторяющуюся подстроку.

    ' '

    Для решения подобной задачи было разработано достаточно алгоритмов, каждый из которых имеет свои преимущества и недостатки. На мой взгляд, самым простым и эффективным является так называемый “наивный алгоритм”.

    1. Суть наивного алгоритма

    Алгоритм основан на матрице совпадений M размерности n х n. Элементы этой матрицы определяются следующим образом:

    ss65

    Такая матрица симметрична относительно главной диагонали. Поэтому надо вычислить только элементы над ней или под ней. Диагонали из смежных ‘1’, за исключением главной, представляют повторения в строке y, там-то и нужно искать максимальные повторяющиеся подстроки. Вот пример матрицы совпадений для строки PABCQRABCSABTU.

    j 1 2 3 4 5 6 7 8 9 10 11 12 13 14
    i P A B C Q R A B C S A B T U
    1 P 1 0 0 0 0 0 0 0 0 0 0 0 0 0
    2 A 0 1 0 0 0 0 1 0 0 0 1 0 0 0
    3 B 0 0 1 0 0 0 0 1 0 0 0 1 0 0
    4 C 0 0 0 1 0 0 0 0 1 0 0 0 0 0
    5 Q 0 0 0 0 1 0 0 0 0 0 0 0 0 0
    6 R 0 0 0 0 0 1 0 0 0 0 0 0 0 0
    7 A 0 1 0 0 0 0 1 0 0 0 1 0 0 0
    8 B 0 0 1 0 0 0 0 1 0 0 0 1 0 0
    9 C 0 0 0 1 0 0 0 0 1 0 0 0 0 0
    10 S 0 0 0 0 0 0 0 0 0 1 0 0 0 0
    11 A 0 1 0 0 0 0 1 0 0 0 1 0 0 0
    12 B 0 0 1 0 0 0 0 1 0 0 0 1 0 0
    13 T 0 0 0 0 0 0 0 0 0 0 0 0 1 0
    14 U 0 0 0 0 0 0 0 0 0 0 0 0 0 0

    Из приведенной выше матрицы можно видеть, что максимальными повторяющимися подстроками в данном примере являются ABC, с вхождениями y(2, 4) и y(7, 9), и AB, с вхождениями y(2, 3), y(7, 8) и y(11, 12). Легко выбрать более длинную из них, а именно, ABC.

    Как уже упоминалось, поскольку матрица симметрична, достаточно вычислить элементы над главной диагональю, M(1…n-1,i+1…n), то есть всего n(n-1)/2 элементов. Таким образом, оценивание матрицы требует времени, пропорционального O(n2).

    Уяснив для себя общие черты алгоритма, можно смело приступать к программированию. Я, не долго заморачиваясь, написал небольшую программку на Delphi, которая демонстрирует работу наивного алгоритма.

    2. Наивный алгоритм в действии

    Запускаем Delphi, создаем новый проект и укладываем на форму 2 Edit’а, 1 кнопку и 1 label. Должно получиться примерно следующее:

    главная форма приложения

    главная форма приложения

    В Edit’ы будем вписывать анализируемые стоки и выводить в Label результат сравнения. Функция, реализующая работы наивного алгоритма выглядит следующим образом (с краткими комментариями):

    function TForm1.GetSequence(str1, str2: string): string;
    var i,j,max, max_i,max_j:integer;
    Matrix: array of array of integer;
    begin
    //устанавливаем размерность массива
    SetLength(Matrix, Length(str1));
    for I:=0 to length(Matrix)-1 do
    SetLength(Matrix[i],length(str2));
    //строим матрицу
    max:=0;
    for i:=0 to length(Matrix)-1 do
    for j:=0 to length(Matrix[i])-1 do
    begin
    if (i=0)or(j=0) then
    Matrix[i,j]:=0
    else
    if str1[i]<>str2[j] then
    Matrix[i,j]:=0
    else
    begin
    Matrix[i,j]:=Matrix[i-1,j-1]+1;
    if Matrix[i,j]>max then
    begin
    max:=Matrix[i,j];
    max_i:=i;
    max_j:=j;
    end;
    end;
    end;
    //Составляем строку по str1 i
    result:='';
    for I:=max_i-max+1 to max_i do
    Result:=result+str1[i];
    end;

    Как видите, все достаточно просто. Берем один динамический массив, устанавливаем его размеры и, применяя формулу, представленную вышезаполняем массив нулями и единицами. В последнем цикле прозодимся по элементам и выбираем необходимую подстроку.

    Результат работы программы представлен на рисунке:

    Результат работы наивного алгоритма

    Результат работы наивного алгоритма

    Можно бесконечно долго совершенствовать алгоритмы поиска и анализа строк, но, на мой взгляд, наивный алгоритм наиболее подходящее решения для работы небольших программ. За сим откланиваюсь. Будут вопросы, пожелания – пишите :)

    Мой блог находят по следующим фразам

    ---------------------------
    Сколько раз сталкивался с ситуацией, когда человек говорил "Я ищу работу, но не могу никак найти. Что делать не знаю". Теперь знайте - просто оставьте свое резюме на KeyWork.ru и работодатели найдут Вас сами.
    ---------------------------

    Related posts:

    Автор Vlad в 5:10 am

    Метки: , , , , ,

Ваш ответ

Внимание: Все комментарии модерируются, и это может вызвать задержку их публикации. Отправлять комментарий заново не требуется.

Пожалуйста, заключайте исходный код в тэги [code][/code].