Помощь - Поиск - Пользователи - Календарь
Полная версия: поиск в строке
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
lopata
Строка называется m-знаковой, если она содержит m различных знаков. Строки a, ab und abcbaac 3-знаковые, а строка abcd 4-знаковая.
Дана строка s и число m , так что 1 <= m <= Length(s).
Необходимо написать
FUNCTION MaxMChainLen(s: STRING, m: INTEGER): INTEGER;
которая вычисляет длину самой длинной m-знаковой строки, которая содержится в строке s.

Идея сама понятна. Начала с самого простого. Просто вычисляю самую первую m-знаковой подстроку, которая попадется. А потом, насколько понимаю, нужно делать по алгоритму Кнута-Морриса-Пратта.

Моя идея, что, начиная с первого знака строки s, я копирую этот каждый знак в строку subs. если новый знак строки s не содержиться в строке subs, то увеличиваю счетчик на единицу. и так до тех пор, пока счетчик не будет равен m. А потом просто вычисляю длину строки subs.

Походу я что-то там намутила с циклами.. Код компилируется, а ничего не выдается.
Гляньте, пожалуйста.


FUNCTION MaxMChainLen(s: STRING; m: INTEGER):INTEGER;
VAR
i,j, count: INTEGER;
subs : STRING;
BEGIN
count := 0;
subs := '';
WHILE (count <> m) DO BEGIN
FOR i := 1 to Length(s) DO BEGIN
IF ( i = 1) THEN BEGIN
subs := s[i];
count := count+1;
END (* if *)
ELSE BEGIN
FOR j := 1 to Length(subs) DO BEGIN
IF (s[i]<> subs[j]) THEN
count := count+1;
subs:= subs+s[i];
END; (* for *)
END; (* else *)
END; (* for *)
END;(* while *)
END; (* MaxMChainLen *)

Unconnected
Мне кажется, тут можно обойтись без Кнута-Морриса-Пратта, только вот правильно ли я понял задание.. Вот почему строки a и ab являются трёхсимвольными? По-моему, одно- и двух символьными соответственно.
lopata
Цитата(Unconnected @ 20.03.2010 16:55) *

Мне кажется, тут можно обойтись без Кнута-Морриса-Пратта, только вот правильно ли я понял задание.. Вот почему строки a и ab являются трёхсимвольными? По-моему, одно- и двух символьными соответственно.

ну можно и без него)
здесь не a и ab , а a, ab Запятая в этом примере тоже является символом
Unconnected
Можно так:

const mn:set of char=[];
var s:string;
i,j,m,ind,count:byte;
sym:array [1..255] of byte;

begin
writeln('Vvedite Stroku');
readln(s);
writeln('Vvedite M');
readln(m);
fillchar(sym,sizeof(byte)*length(s),0);ind:=0;
for i:=1 to length(s) do begin
if not(s[i] in mn) then begin
inc(ind);
for j:=1 to length(s) do if s[j]=s[i] then inc(sym[ind]);
end;
include(mn,s[i]);
end;
for i:=1 to ind-1 do begin
if sym[i]>sym[i+1] then begin
count:=sym[i+1];
sym[i+1]:=sym[i];
sym[i]:=count;
end;
end;
count:=0;
for i:=1 to m do begin
inc(count,sym[ind]);
dec(ind);
end;
writeln('Maxlength=',count);
readln;
end.


lopata
насколько я понимаю, const mn:set of char=[]; это множество. А на учебе мы множества на паскале вообще никогда не применяли...

Добавлено через 2 мин.
поэтому этот код для меня загадка
Unconnected
Тогда так:

var s:string;
i,j,m,ind,mnind,count:byte;
sym:array [1..255] of byte;
mn:array[1..255] of char;

function check(c:char):boolean;
var u:byte;
begin
check:=false;
for u:=1 to mnind do if c=mn[u] then begin
check:=true;
break;
end;
end;

begin
writeln('Vvedite Stroku');
readln(s);
writeln('Vvedite M');
readln(m);
fillchar(sym,sizeof(byte)*length(s),0);
fillchar(mn,sizeof(char)*length(s),#0);
ind:=0;mnind:=0;
for i:=1 to length(s) do begin
if not(check(s[i])) then begin
inc(ind);inc(mnind);
for j:=1 to length(s) do if s[j]=s[i] then inc(sym[ind]);
end;
mn[mnind]:=s[i];
end;
for i:=1 to ind-1 do begin
if sym[i]>sym[i+1] then begin
count:=sym[i+1];
sym[i+1]:=sym[i];
sym[i]:=count;
end;
end;
count:=0;
for i:=1 to m do begin
inc(count,sym[ind]);
dec(ind);
end;
writeln('Maxlength=',count);
readln;
end.




Функции вы проходили, надеюсь..
lopata
А можешь, пожалуйста, пояснить как ты это делал. Не понимаю твой код.
lopata
Неправильно работает
Client
пример приведи
lopata
Спасибо, конечно, мне не нужно мне было свой код писать. мне бы со своим разобраться..

Добавлено через 4 мин.
Цитата(Client @ 20.03.2010 21:55) *

пример приведи

ввожу строка: adeeadfcce
m = 4.
выдает 9. Хотя должно 7.
ввожу строку : accaeadad
m = 3.
выдает 9.а должно 6.
Unconnected
Цитата
Неправильно работает


Ну, у меня при строке abccccc и m=3 выдаёт ответ 7.

Как работает - сначала находил, сколько раз каждый символ встречается в строке, заносил эти данные в массив, потом упорядочивал его по возрастанию, а потом суммировал M элементов с конца массива, получается наибольшая длина. Могу комментарии расставить.

Ну, а чего ж ты после первого моего решения не сказала, что свой код нужен?smile.gif
lopata
Цитата(Unconnected @ 20.03.2010 22:03) *

Ну, у меня при строке abccccc и m=3 выдаёт ответ 7.

Как работает - сначала находил, сколько раз каждый символ встречается в строке, заносил эти данные в массив, потом упорядочивал его по возрастанию, а потом суммировал M элементов с конца массива, получается наибольшая длина. Могу комментарии расставить.

Ну, а чего ж ты после первого моего решения не сказала, что свой код нужен?smile.gif

Я же с самого начала попросила разобраться что там в моем не так)
и в самом задании конкретно указано, что должна быть функции. Комментарии расставлять не стоит, буду свой код мучать.

Изображение
неверно же..

Добавлено через 5 мин.
Цитата(lopata @ 20.03.2010 22:05) *

Я же с самого начала попросила разобраться что там в моем не так)
и в самом задании конкретно указано, что должна быть функции. Комментарии расставлять не стоит, буду свой код мучать.

Изображение
неверно же..

сорри за фиговый скрин(

Добавлено через 5 мин.
Прости, пожалуйста give_rose.gif
У тебя все верно) это у меня мозги опухли)
Unconnected
Цитата
ввожу строка: adeeadfcce
m = 4.
выдает 9. Хотя должно 7.


Должно 9.


Цитата
ввожу строку : accaeadad
m = 3.
выдает 9.а должно 6.


Неправда. Выдаёт 8, как и должно быть.
lopata
Цитата(lopata @ 20.03.2010 22:05) *

Прости, пожалуйста give_rose.gif
У тебя все верно) это у меня мозги опухли)

Или нет...честно говоря больше ничего не понимаю

Добавлено через 4 мин.
Цитата(Unconnected @ 20.03.2010 22:22) *

Должно 9.
Неправда. Выдаёт 8, как и должно быть.

А может сказать почему должно быть 9 и 8 ?
Unconnected
Цитата
ввожу строку : accaeadad
m = 3.


'a' - 4 символа
'c' - 2 символа
'd' - 2 символа

4+2+2=8
lopata
Цитата(Unconnected @ 20.03.2010 22:46) *

'a' - 4 символа
'c' - 2 символа
'd' - 2 символа

4+2+2=8

Блин.Точно.
Но:
adeeadf cce
1233124
7. должно быть



Добавлено через 2 мин.
Блин. Неважно. А что я вообще делаю не так? Чем плох мой алгоритм?
Unconnected
Цитата

Моя идея, что, начиная с первого знака строки s, я копирую этот каждый знак в строку subs. если новый знак строки s не содержиться в строке subs, то увеличиваю счетчик на единицу. и так до тех пор, пока счетчик не будет равен m. А потом просто вычисляю длину строки subs.


А что будет, если видов символов в строке S будет больше M? Тебе же надо найти наибольшую возможную длину строки, значит, надо искать длиннейшие последовательности из одинаковых символов и суммировать их длины.
lopata
Цитата(Unconnected @ 20.03.2010 23:54) *

А что будет, если видов символов в строке S будет больше M? Тебе же надо найти наибольшую возможную длину строки, значит, надо искать длиннейшие последовательности из одинаковых символов и суммировать их длины.

Это понятно...А вот как найти эти длиннейшие последовательности?..

Добавлено через 2 мин.
А если это делать полным перебором?
Unconnected
Бежим по строке, считаем, сколько раз каждый символ в ней встречается. Упорядочиваем эту информацию например по возрастанию, я заносил в массив. Т.е. самый последний элемент массива будет хранить длину длиннейшей последовательности, предпоследний элемент - длину второй по длине последовательности, и так далее. В итоге складываем M длин с конца.

Добавлено через 1 мин.
blink.gif каким перебором, куда, зачем?..
lopata
[quote name='Unconnected' date='21.03.2010 0:05' post='143223']
Бежим по строке, считаем, сколько раз каждый символ в ней встречается. Упорядочиваем эту информацию например по возрастанию, я заносил в массив. Т.е. самый последний элемент массива будет хранить длину длиннейшей последовательности, предпоследний элемент - длину второй по длине последовательности, и так далее. В итоге складываем M длин с конца.

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

Добавлено через 2 мин.
Мне кажется, должен быть какой-то другой алгоритм. Учитывая что мы сейчас на занятиях проходим алгоритмы поиска подстроки в строке..
volvo
Что-то меня терзают сомнения, что это правильно, но все-таки потестируй на ВСЕХ своих тестах:
function maxChain(s: string; len: integer): integer;
var
i: integer;
arr: array[1 .. 255] of byte;

begin
for i := 1 to 255 do arr[i] := 255;
arr[1] := 1;
for i := 2 to length(s) do
begin
if pos(s[i], s) < i then arr[i] := arr[i - 1]
else arr[i] := arr[i - 1] + 1;
end;

i := 0;
repeat
inc(i)
until arr[i + 1] > len;

maxChain := i;
end;

var s: string;
begin
s := 'adeeadfcce';
writeln(maxChain(s, 4));
end.
Unconnected
Проснулся сегодня и понял, что в моём коде сортировка неправильная. Так лучше:

var s:string;
i,j,m,ind,mnind,count:byte;
sym:array [1..255] of byte;
mn:array[1..255] of char;

function check(c:char):boolean;
var u:byte;
begin
check:=false;
for u:=1 to mnind do if c=mn[u] then begin
check:=true;
break;
end;
end;

begin
writeln('Vvedite Stroku');
readln(s);
writeln('Vvedite M');
readln(m);
fillchar(sym,sizeof(byte)*length(s),0);
fillchar(mn,sizeof(char)*length(s),#0);
ind:=0;mnind:=0;
for i:=1 to length(s) do begin
if not(check(s[i])) then begin
inc(ind);inc(mnind);
for j:=1 to length(s) do if s[j]=s[i] then inc(sym[ind]);
end;
mn[mnind]:=s[i];
end;
for i:=1 to ind-1 do begin
for j:=i+1 to ind do begin
if sym[i]>sym[j] then begin
count:=sym[j];
sym[j]:=sym[i];
sym[i]:=count;
end;
end;
end;
count:=0;
for i:=1 to m do begin
inc(count,sym[ind]);
dec(ind);
end;
writeln('Maxlength=',count);
readln;
end.


lopata
спасибо,volvo, но оно действительно неправильно вычисляет.
s := aaaabbccccc;
m := 1;
А значение функции 4.

Unconnected, а может все-такие проставить пожалуйста комментарии?


Добавлено через 2 мин.
Блин..
volvo, а можешь объяснить что ты делал?
Unconnected

var s:string;
i,j,m,ind,mnind,count:byte;
sym:array [1..255] of byte; //массив, в каждой ячейке которого содержится количество вхождений в строку
//некого символа
mn:array[1..255] of char; //массив, в котором хранятся уже посчитанные символы.

function check(c:char):boolean; //проверка символа на то, считали ли уже количество его вхождений в строку
var u:byte;
begin
check:=false;
for u:=1 to mnind do if c=mn[u] then begin
check:=true;
break;
end;
end;

begin
writeln('Vvedite Stroku');
readln(s);
writeln('Vvedite M');
readln(m);
fillchar(sym,sizeof(byte)*length(s),0); // инициализация обоих массивов
fillchar(mn,sizeof(char)*length(s),#0);//
ind:=0;mnind:=0; //и переменных
for i:=1 to length(s) do begin //бежим по строке
if not(check(s[i])) then begin //если ещё не считали количество вхождений очередного элемента, то посчитаем
inc(ind);inc(mnind);
for j:=1 to length(s) do if s[j]=s[i] then inc(sym[ind]); //бежим по строке и считаем вхождения
end;
mn[mnind]:=s[i]; //заносим в массив элемент,вхождения которого считали, чтобы не считать их снова, если
//он встретится опять
end;
for i:=1 to ind-1 do begin //в каждой ячейке массива sym содержится количество вхождений какого-то
for j:=i+1 to ind do begin //элемента. Какого, нам не важно. Сортируем этот массив, "пузырьком".
if sym[i]>sym[j] then begin
count:=sym[j];
sym[j]:=sym[i];
sym[i]:=count;
end;
end;
end;
count:=0;
for i:=1 to m do begin //отсортировали. Длины в массиве syn хранятся по возрастанию, нам надо взять
inc(count,sym[ind]); // M самых больших. Идём с конца (заметь, чему равно ind здесь) и суммируем эти
dec(ind); //элементы в count.
end;
writeln('Maxlength=',count);
readln;
end.

lopata
Unconnected, cпасибо большое. буду разбираться..
lopata
Честно говоря, все равно что-то неверно
Потому как
s = aaaabbbccccc
m= 2
Ответ 9.
А должен быть 8
(bbbccccc)

Добавлено через 8 мин.
Или я, или ты неправильно поняли задание
Unconnected
Цитата
s = aaaabbbccccc
m= 2
Ответ 9.
А должен быть 8
(bbbccccc)


Ответ должен быть 9, aaaaccccc .
lopata
я поняла почему 9. прото мне казалось, что символы должны подряд стоять...
то есть
Так aaaa bbbccccc ответ 8;
А так aaaacccccbbb 9;
А этого в самом задании не написано. Только то, что написала.
volvo
Цитата
прото мне казалось, что символы должны подряд стоять...
Правильно казалось. Символы должны стоять именно подряд, это то, что записано в задании:
Цитата
которая вычисляет длину самой длинной m-знаковой строки, которая содержится в строке s.
Не "состоит из символов, из которых состоит s", а "содержится в s", понимаешь? Содержится - значит целиком: bca - содержится в abcabc, а bcb - уже нет...

Update
Вот это:
function maxChain(s: string; len: integer): integer;
var
i, offset, max: integer;
subs: string;
begin
max := 0;
for i := 1 to length(s) do
begin
offset := 0; subs := '';
while (i + offset <= length(s)) do
begin
if pos(s[i + offset], subs) > 0 then inc(offset)
else begin
subs := subs + s[i + offset];
if length(subs) > len then break;
inc(offset);
end;
end;

if max < offset then max := offset;
end;

maxChain := max;
end;

var
s: string;
begin
s := 'aaaabbbccccc'; // m = 2; => 8
// s := 'adeeadfcce'; // m = 4; => 7
// s := 'accaeadad'; // m = 3; => 6
// s := 'aaaabbccccc'; // m = 1; => 5
writeln(maxChain(s, 2));
end.
выдает ожидаемые результаты на всех тестах, которые ты здесь приводила...
lopata
Цитата(volvo @ 24.03.2010 12:26) *

Правильно казалось. Символы должны стоять именно подряд, это то, что записано в задании:
Не "состоит из символов, из которых состоит s", а "содержится в s", понимаешь? Содержится - значит целиком: bca - содержится в abcabc, а bcb - уже нет...


Логично...
Спасибо
lopata
Тольконе совсем поняла что ты делал с Max.
volvo
Искал наибольшее, что и требовалось... На каждой итерации в Offset получаем количество символов в M-буквенном слове, которое начинается с I-той позиции строки. Если среди всех Offset-ов найдем максимальный, то получим то, что требовалось в задаче: длину максимального М-буквеного слова.
lopata
Всё, поняла. спасибо большое.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.