Строка называется 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 *)
Мне кажется, тут можно обойтись без Кнута-Морриса-Пратта, только вот правильно ли я понял задание.. Вот почему строки a и ab являются трёхсимвольными? По-моему, одно- и двух символьными соответственно.
Можно так:
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.
насколько я понимаю, const mn:set of char=[]; это множество. А на учебе мы множества на паскале вообще никогда не применяли...
Добавлено через 2 мин.
поэтому этот код для меня загадка
Тогда так:
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.
А можешь, пожалуйста, пояснить как ты это делал. Не понимаю твой код.
Неправильно работает
пример приведи
Спасибо, конечно, мне не нужно мне было свой код писать. мне бы со своим разобраться..
Добавлено через 4 мин.
Бежим по строке, считаем, сколько раз каждый символ в ней встречается. Упорядочиваем эту информацию например по возрастанию, я заносил в массив. Т.е. самый последний элемент массива будет хранить длину длиннейшей последовательности, предпоследний элемент - длину второй по длине последовательности, и так далее. В итоге складываем M длин с конца.
Добавлено через 1 мин.
каким перебором, куда, зачем?..
[quote name='Unconnected' date='21.03.2010 0:05' post='143223']
Бежим по строке, считаем, сколько раз каждый символ в ней встречается. Упорядочиваем эту информацию например по возрастанию, я заносил в массив. Т.е. самый последний элемент массива будет хранить длину длиннейшей последовательности, предпоследний элемент - длину второй по длине последовательности, и так далее. В итоге складываем M длин с конца.
Добавлено через 1 мин.
то есть в массив тоже заносишь колво одинаковых символов?
но ведь получается тогда, насколько поняла, что если потом складываешь с конца, то не попорядку этипоследовательности...
Добавлено через 2 мин.
Мне кажется, должен быть какой-то другой алгоритм. Учитывая что мы сейчас на занятиях проходим алгоритмы поиска подстроки в строке..
Что-то меня терзают сомнения, что это правильно, но все-таки потестируй на ВСЕХ своих тестах:
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.
Проснулся сегодня и понял, что в моём коде сортировка неправильная. Так лучше:
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.
спасибо,volvo, но оно действительно неправильно вычисляет.
s := aaaabbccccc;
m := 1;
А значение функции 4.
Unconnected, а может все-такие проставить пожалуйста комментарии?
Добавлено через 2 мин.
Блин..
volvo, а можешь объяснить что ты делал?
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.
Unconnected, cпасибо большое. буду разбираться..
Честно говоря, все равно что-то неверно
Потому как
s = aaaabbbccccc
m= 2
Ответ 9.
А должен быть 8
(bbbccccc)
Добавлено через 8 мин.
Или я, или ты неправильно поняли задание
я поняла почему 9. прото мне казалось, что символы должны подряд стоять...
то есть
Так aaaa bbbccccc ответ 8;
А так aaaacccccbbb 9;
А этого в самом задании не написано. Только то, что написала.
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.
Тольконе совсем поняла что ты делал с Max.
Искал наибольшее, что и требовалось... На каждой итерации в Offset получаем количество символов в M-буквенном слове, которое начинается с I-той позиции строки. Если среди всех Offset-ов найдем максимальный, то получим то, что требовалось в задаче: длину максимального М-буквеного слова.
Всё, поняла. спасибо большое.