Файл: Обработка символьных строк.doc

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 04.12.2023

Просмотров: 935

Скачиваний: 9

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.


  1. динамический массив (список), для этого далее мы будем использовать тип данных list (список) из библиотеки STL; не забудьте, что нужно подключить заголовочный файл list:

#include

  1. вначале создаём список символов, состоящий из одного первого символа строки:

list c( s[0] );

  1. если нашли новую (не первую) цепочку максимальной длины, добавляем новый символ в список с помощью метода push_back:

c.push_back( s[i] );

  1. если нашли новую самую длинную цепочку с длиной бОльшей, чем все предыдущие, очищаем список и добавляем в него новый символ:

c.clear();

c.push_back( s[i] );

  1. после окончания обработки нужно вывести все символы и длины цепочек, удобнее всего использовать для этого особую форму цикла for; получается почти так же, как и на Python:

for( char c1: c )

cout << c1 << ' ' << maxLen << endl;

  1. вот полная программа:

#include

#include

#include

#include

using namespace std;

int main()

{

ifstream F("k8.txt");

string s;

getline( F, s );

int maxLen = 1, curLen = 1;

list c(s[0]);

for( int i = 1; i < s.length(); i++ )

if( s[i] == s[i-1] ) {

curLen ++;

if( curLen == maxLen )

c.push_back(s[i]);

else if( curLen > maxLen ) {

maxLen = curLen;

c.clear();

c.push_back( s[i] );

}

}

else curLen = 1;

for( char c1: c )

cout << c1 << ' ' << maxLen << endl;

}

Ещё пример задания:


Р-05. В текстовом файле k8.txt находится цепочка из символов, в которую могут входить заглавные буквы латинского алфавита A…Z и десятичные цифры. Найдите длину самой длинной подцепочки, состоящей из одинаковых символов. Выведите сначала символ, из которого строится цепочка, а затем через пробел – длину этой цепочки.

Замечание (Б.С. Михлин). Может случиться так, что в файле будут несколько самых длинных цепочек (одинаковой длины), состоящих из разных символов. На этот случай условие задачи требует уточнения – какой именно символ выводить в ответе? Далее мы будем считать, что в этом случае нужно вывести символ, который формирует первую цепочку максимальной длины.

Решение:

  1. сначала нужно открыть файл и прочитать все символы в символьную строку:

with open("k8.txt", "r") as F:

s = F.readline()

  1. теперь задача свелась к определению наибольшего количества подряд идущих одинаковых символов в символьной строке s (этот алгоритм приведён в начале файла)

  2. полная программа на языке Python:


with open( "k8.txt", "r" ) as F:

s = F.readline()

maxLen, curLen, c = 1, 1, s[0]

for i in range(1, len(s)):

if s[i] == s[i-1]:

curLen += 1

if curLen > maxLen:

maxLen = curLen

c = s[i]

else:

curLen = 1

print( c, maxLen )

Обратим внимание, что условие

if curLen > maxLen: ...

гарантирует, что будет запомнена именно первая цепочка максимальной длины, так как это условие выполнится, когда новая цепочка строго длиннее предыдущего «рекорда». Если бы нужно было вывести символ, формирующий последнюю из самых длинных цепочек, неравенство следовало бы сделать нестрогим:

if curLen >= maxLen: ...

Решение (программа на языке Pascal):

  1. далее мы будем использовать язык PascalABC.NET, который обладает двумя важными достоинствами, упрощающими решение таких задач:

  • позволяет легко переключать входной поток с консоли на нужный файл:

assign( input, 'k8.txt' );

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

  • не имеет ограничения на длину строк (переменных типа string); в устаревших версиях языка Pascal длина строки не может превышать 255 символов

  1. читаем одну строку из файла в строковую переменную s:

readln(s);

  1. теперь можно в цикле перебрать все символы строки s, начиная со второго (чтобы сравнивать его с предыдущим):

for i:=2 to Length(s) do

обработать пару s[i-1] и s[i]

  1. обработка выполняется по алгоритму, описанному выше (см. программу на Python)

  2. полная программа на языке Pascal:

var maxLen, curLen, i: integer;

s: string;

c: char;

begin

assign(input, 'k8.txt');

readln(s);

maxLen := 1;

curLen := 1;

c := s[1];

for i:=2 to Length(s) do

if s[i] = s[i-1] then begin

curLen := curLen + 1;

if curLen > maxLen then begin

maxLen := curLen;

c := s[i];

end

end

else

curLen := 1;

writeln(c, ' ', maxLen);

end.

Решение (программа на языке C++):

  1. в C++ удобно работать с файлами через файловые потоки; для того, чтобы использовать эту возможность, нужно подключить заголовочный файл fstream:

#include

  1. теперь можно открыть файловый поток, связать его с нужным файлом и прочитать из потока строку в переменную типа string:

ifstream F("k8.txt");

string s;

getline( F, s );

  1. алгоритм обработки строки тот же, что и в программах на языках Python и Pascal, рассмотренных выше

  2. поскольку в программе используется много объектов из пространства имён std, имеет смысл подключить его в начале программы:


using namespace std;

  1. полная программа на языке C++:

#include

#include

#include

using namespace std;

int main()

{

ifstream F("k8.txt");

string s;

getline( F, s );

int maxLen = 1, curLen = 1;

char c = s[0];

for( int i = 1; i < s.length(); i++ )

if( s[i] == s[i-1] ) {

curLen ++;

if( curLen > maxLen ) {

maxLen = curLen;

c = s[i];

}

}

else curLen = 1;

cout << c << ' ' << maxLen;

}

Ещё пример задания:


Р-04. (А.М. Кабанов) В текстовом файле k7.txt находится цепочка из символов латинского алфавита A, B, C, D, E. Найдите количество цепочек длины 3, удовлетворяющих следующим условиям:

  • 1-й символ – один из символов B, C или D;

  • 2-й символ – один из символов B, D, E, который не совпадает с первым;

  • 3-й символ – один из символов B, C, E, который не совпадает со вторым.

Решение:

  1. Считывание из файла и перебор символов аналогичен задачам Р00-Р02 (см. ниже).

  2. Переберём все тройки символов. Примем, что переменная i будет хранить номер первого элемента в тройке, то есть, будем рассматривать тройки (s[i], s[i+1], s[i+2]).

  3. Организуем цикл который перебирает значения i от 1 до len(s)-2

for i in range(len(s)-2):

...

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

  2. полная программа на Python:

s = open('k7.txt').read()

count = 0

for i in range(len(s)-2):

if s[i] in 'BCD' and s[i+1] in 'BDE' \

and s[i+2] in 'BCE' and s[i]!=s[i+1] \

and s[i+1]!=s[i+2]:

count += 1

print(count)

Решение (программа на языке PascalABC.NET):

begin

var s: string;

var i, count: integer;

assign(input,'k7.txt');

readln(s);

count:=0;

for i:=1 to Length(s)-2 do

if (s[i] in 'BCD') and (s[i+1] in 'BDE')

and (s[i+2] in 'BCE') and (s[i]<>s[i+1])

and (s[i+1]<>s[i+2]) then

count := count+1;

writeln(count);

end.

Решение (программа на языке С++):

using namespace std;

#include

#include

#include

int main(){

ifstream F("k7.txt");

string s;

getline( F, s );

int count = 0;

for( int i = 0; i < s.length()-2; i++ )

if( (s[i]=='B' || s[i]=='C' || s[i]=='D')

&& (s[i+1]=='B' || s[i+1]=='D' || s[i+1]=='E')

&& (s[i+2]=='B' || s[i+2]=='C' || s[i+2]=='E')


&& s[i]!=s[i+1] && s[i+1]!=s[i+2] )

count++;

cout << count;

}

Ещё пример задания:


Р-03. (А.М. Кабанов) В текстовом файле k7.txt находится цепочка из символов латинского алфавита A, B, C, D, E. Найдите максимальную длину цепочки вида EABEABEABE... (составленной из фрагментов EAB, последний фрагмент может быть неполным).

Решение:

  1. Считывание из файла и перебор символов аналогичен задачам Р00-Р02 (см. ниже).

  2. Проверка того, что символ принадлежит цепочке, производится следующим образом. Заметим, что в искомой цепочке чередуется группа из трёх символов (EAB). Пронумеруем символы искомой цепочки, начиная с нуля.



  1. Видно, что позиция каждого символа имеет одинаковый остаток от деления на 3. Позиция есть значения переменной счётчика в момент проверки символа. Поэтому если совпадает символ и соответствующий ему остаток от деления, то он принадлежит цепочке. Для приведённого примера условие проверки выглядит так

if (char == 'E' and count%3==0) or \

(char == 'A' and count%3==1) or \

(char == 'B' and count%3==2):

  1. Если символ не является частью этой цепочки, но может являться её началом (Е), длина цепочки принимается равной единице, в противном случае длина обнуляется

elif (char=='E'):

count = 1

else:

count = 0

  1. Полная программа на языке Python:

s = open('k7.txt').read()

count = 0

maxCount = 0

for char in s:

if (char == 'E' and count%3 == 0) or \

(char == 'A' and count%3 == 1) or \

(char == 'B' and count%3 == 2):

count += 1

if count > maxCount:

maxCount = count

elif (char=='E'):

count = 1

else:

count = 0

print(maxCount)

Решение (полная программа на языке PascalABC.NET):

begin

var s: string;

var i, count, maxCount: integer;

assign(input,'k7.txt');

readln(s);

count:=0;

maxCount:=0;

for i:=1 to Length(s) do

if ((s[i]='E') and (count mod 3=0)) or

((s[i]='A') and (count mod 3=1)) or

((s[i]='B') and (count mod 3=2)) then begin

count := count+1;

if count > maxCount then

maxCount := count;

end

else if s[i]='E' then count:=1

else count := 0;
writeln(maxCount);

end.

Решение (полная программа на языке С++):

using namespace std;

#include

#include

#include

int main(){

ifstream F("k7.txt");

string s;

getline( F, s );

int count = 0, maxCount = 0;

for( int i = 0; i < s.length(); i++ )

if( (s[i] == 'E' && count%3 == 0) ||

(s[i] == 'A' && count%3 == 1) ||


(s[i] == 'B' && count%3 == 2) ) {

count ++;

if( count > maxCount )

maxCount = count;

}

else if(s[i]== 'E') count = 1

else count = 0

cout << maxCount;

}

Решение (программа на Python, М. Магомедов):

with open( "k7.txt", "r" ) as F:

  s = F.readline()

k = ''

while k in s:

  k += 'E'

  if k in s:

    k += 'A'

    if k in s: k += 'B'

print ( len (k) - 1 )

Ещё пример задания:


Р-02. (А.М. Кабанов) В текстовом файле k7.txt находится цепочка из символов латинского алфавита A, B, C, D, E. Найдите длину самой длинной подцепочки, состоящей из символов A, B или C (в произвольном порядке).

Решение:

  1. сначала нужно открыть файл и прочитать все символы в символьную строку:

s = open('k7.txt').read()

  1. теперь можно в цикле перебрать все символы строки s:

for char in s:



  1. теперь задача свелась к определению наибольшей подстроки, состоящей из символов A, B или C, в символьной строке s.

  2. Проверку того, что символ – один из набора A, B, C удобно записывать с помощью условия

if char in 'ABC':

  1. Полная программа на языке Python:

s = open('k7.txt').read()

count = 0

maxCount = 0

for char in s:

if char in 'ABC':

count += 1

if count>maxCount:

maxCount = count

else:

count=0

print(maxCount)

Решение (программа на языке PascalABC.NET):

  1. В начале переключим входной поток с консоли на нужный файл, а затем считаем одну строку из файла в строковую переменную s

assign(input,'k7.txt');

readln(s);

  1. теперь можно в цикле перебрать все символы строки s:

for i:=1 to Length(s) do



  1. обработка символа выполняется по алгоритму, описанному выше (см. программу на Python)

  2. Проверка того, что символ – один из набора A, B, C – в PascalABC.NET записывается аналогично

if s[i] in 'ABC' then

а в среде FreePascal придётся использовать старинный способ:

if s[i] in ['A','B','C'] then

  1. Полная программа на языке PascalABC.NET:

begin

var s: string;

var i, count, maxCount: integer;

assign(input,'k7.txt');

readln(s);

count:=0;

maxCount:=0;

for i:=1 to Length(s) do

if s[i] in 'ABC' then { if s[i] in ['A','B','C'] }

begin

count := count+1;

if count > maxCount then

maxCount := count;

end

else

count := 0;

writeln(maxCount);

end.

Решение (программа на языке C++):

  1. Для чтения из файла подключим заголовочный файл fstream, откроем файловый поток и считаем его в строковую переменную s