roboforum.ru

Технический форум по робототехнике.

Простая задачка по программированию

Простая задачка по программированию

Montoya » 24 мар 2009, 18:09

Готовился я тут к олимпиаде по программированию, и препод дала мне задачу, которая была в 2005 году на городской олимпиаде для НЕпрофессионалов. Сама задача:
Даны 2 фразы, программа должна найти максимальную последовательность символов (не обязательно стоящих подряд), входящую в обе фразы, пример

ПРИШЛА ВЕСНА
РАСТАЯЛ СНЕГ

программа должна вывести РАСН

Я долго долбался над ней, и так ее и не решил, кстати и препод, и ее сын,профессиональный программист, на 100% решить ее не смогли :) Может кто-нибудь попробует ее решить?

ЗЫ сын препода написал эту задачу,используя сложную рекурсию, которая смогла вывести РАСН, но если ввести в его программу "наступила весна" и "расцвели подснежники" программа выводит "НЕ" ....

Re: Простая задачка по программированию

Myp » 24 мар 2009, 18:22

эммм
а тупо перебором?
берём 1 букву 1 строки и ищем её во второй строке
если нашли запоминаем позицию найденной буквы и запоминаем последовательность
берём вторую букву первой строки и ищем в второй строке начиная с запомненной позиции
нету, хорошо, берём третью букву 1 строки и ищем начиная с запомненной позиции во второй строке
нету, хорошо, берём четвёртую букву 1 строки и ищем начиная с запомненной позиции во второй строке
находим и запоминаем результат и позицию
берём 5 букву и ищем начиная с запомненной позиции
таким макаром прогоняем все комбинации возможные

их конечно будет дофига комбинаций особенно если предложение длинное
но в итоге получим список возможных вариантов последовательностей в строке и выберем наилучший

Re: Простая задачка по программированию

Montoya » 24 мар 2009, 18:40

Ну у меня похожие мысли,я просто вытащил все буквы, которые есть в обоих фразах и запомнил их координаты... надо подумать над перебором

Re: Простая задачка по программированию

Myp » 24 мар 2009, 18:44

кстати да
для быстроты надо удалить все буквы которые встречаются один раз

Re: Простая задачка по программированию

Denis_Wozniak » 24 мар 2009, 19:38

Программа готова!
"наступила весна" и "расцвели подснежники" программа выводит "НЕ"

2 варианта ответа!: "АСВЕСН" и "АСИ ЕН"

Если нужен код, тогда в личку стучитесь. 8)

Добавлено спустя 3 минуты 16 секунд:
Да, бог с ней.

Код: Выделить всёРазвернуть
Dim T1 As String, T2 As String, MaxT As String, Len1 As Long, Len2 As Long

Private Sub Main()
T1 = "наступила весна"
T2 = "расцвели подснежники"
Len1 = Len(T1)
Len2 = Len(T2)

Perebor "", 0, 0
Print MaxT
End Sub

Sub Perebor(ByVal Combination As String, N1 As Long, N2 As Long)
Dim I As Long, Nn As Long, Ss As String

For I = N1 + 1 To Len1
    Ss = Mid(T1, I, 1)
    Nn = FindN(N2 + 1, Ss)
    If Nn > 0 Then
        Perebor Combination + Ss, I, Nn
    Else
        If Len(Combination) > Len(MaxT) Then MaxT = Combination
    End If
Next I
End Sub

Function FindN(ByVal n As Long, Buka As String)
FindN = InStr(n, T2, Buka)
End Function


На бейсике быстрее просто :pardon:

Добавлено спустя 4 минуты 40 секунд:
Задача десяти минут!

Re: Простая задачка по программированию

Montoya » 24 мар 2009, 19:41

Хы, пасиб.... еще бы ща понять что оно делает и попробывать это перекинуть на си или хотябы на паскаль.... Лан, вечером попробую разобраться, а то ща бошка всякой социологией и экономикой забита :bad: ....
ЗЫ скорее всего организаторы этой олимпиады взяли эту задачу из какой-нибудь книги по васику :)

Re: Простая задачка по программированию

Denis_Wozniak » 24 мар 2009, 20:04

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

Добавлено спустя 20 минут 41 секунду:
Нее.
Вломину переписывать.

Вот расшифровочка

Len - Length
Mid - Copy
Instr - Pos

Вот собстно и всё.

Re: Простая задачка по программированию

=DeaD= » 24 мар 2009, 21:16

2Denis: Решение конечно похоже на действующее (в ломы разбирать бейсиковый код с глобальными переменными :)), но не оптимальное.

Оптимальное решение такой задачи - классическое динамическое программирование.

Кто на олимпиады ходит - должен знать этот метод :wink:

Re: Простая задачка по программированию

Montoya » 24 мар 2009, 21:21

Хм....ща будем гуглить :oops:

Re: Простая задачка по программированию

=DeaD= » 24 мар 2009, 21:25

Ага, почитай, очень мощный метод, очень часто в задачах применяется, и самое главное - нереально быстрый :)

Если что задавай вопросы, но описывать подходы с нуля - ломает :) да и примеров надо кучу приводить...

Добавлено спустя 54 секунды:
PS 2Denis: Если на олимпиадах участвуешь по информатике - тоже обязательно метод почитай, в каждой второй-третьей задаче почти встречается :)

Re: Простая задачка по программированию

Denis_Wozniak » 24 мар 2009, 22:28

Хм...
ДинамоПрогр-ие?
Вы предлагате разбросать строки в массивы? :)
В Паскале со строкой, как массивом работать можно.

Re: Простая задачка по программированию

Montoya » 24 мар 2009, 22:36

Та суть метода не в этом, там , в часности для нахождения НОП (наибольшая общая подпоследовательность), заполняется таблица значениями функции (которая определяет max длину), которые были вычислены раньше.Или я не прав?

Добавлено спустя 1 минуту 54 секунды:
Будем решать эту задачу методом динамического программирования. Для этого опишем подзадачи, на которые мы будем разбивать нашу задачу. Мы напишем функцию LCS(p, q), которая находит длину НОП для двух начальных участков a1, …, ap и b1, …, bq наших последовательностей. Пусть для всех пар q и p (p < n, q < m), мы задачу решать уже научились. Попробуем вычислить LCS(n, m). Рассмотрим два случая:


1) an= bm. Тогда LCS(n, m)=LCS(n-1, m-1)+1.


2) an≠ bm. Тогда LCS(n, m)=max(LCS(n, m-1), LCS(n-1, m)).


Пользуясь этими формулами, мы можем заполнить таблицу значений LCS(p, q) для всех p и q последовательно: сначала заполняем первую строчку слева направо, затем вторую и т.д. Последнее число в последней строке и будет ответом на поставленную задачу.


Данный алгоритм требует порядка O(nm) операций.

Re: Простая задачка по программированию

Denis_Wozniak » 24 мар 2009, 22:37

Да, вроде так.
Грубо говоря не делать много раз "Pos" для одного и того же символа.

Re: Простая задачка по программированию

bolt » 24 мар 2009, 23:01

для быстроты надо удалить все буквы которые встречаются один раз

отличная идея! Останутся лишь те, что есть в каждой из фраз. А уж выбрать самую длинную строку не сложно.

Re: Простая задачка по программированию

Montoya » 25 мар 2009, 00:15

Блин, кому-то не сложно, а у кого-то уже мозг кипит от динамического программирования.....

Добавлено спустя 59 минут 40 секунд:
Вобщем вот, немного переделанный код (с ru.wikipedia.org/wiki/Наибольшая_общая_подпоследовательность), фразы вводить без пробелов
Код: Выделить всёРазвернуть
#include <iostream>
#include <conio.h>
using namespace std;
int main() {
char a[50];
char b[50];
cin>>a;
cin>>b;
int max_len[50][50];
for(int i = strlen(a) - 1; i >= 0; i--)
      {
         for(int j = strlen(b) - 1; j >= 0; j--)
         {
            if(a[i] == b[j])
            {
               max_len[i][j] = 1 + max_len[i+1][j+1];
            }
            else
            {
               max_len[i][j] = max(max_len[i+1][j], max_len[i][j+1]);
            }
         }
      }
      char res[50];
      int k=0;
      for(int i = 0, j = 0; max_len[i][j]!=0 && i<strlen(a) && j<strlen(b); )
      {
         if(a[i] == b[j])
         {
            res[k]=a[i];
            k++;
            i++;
            j++;
         }
         else
         {
            if(max_len[i][j] == max_len[i+1][j])
               i++;
            else
               j++;
         }
      }

cout<<res<<endl;
getch();
}


Rambler\'s Top100 Mail.ru counter