Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
0 / 0 / 0
Регистрация: 14.02.2022
Сообщений: 12

Ускорение работы алгоритма замены всех вхождений подстроки в строке

14.02.2022, 19:31. Показов 2266. Ответов 26

Студворк — интернет-сервис помощи студентам
Возникла следующая проблема. Написал программу, которая заменяет все вхождения подстроки в строке. Всё работает, но есть одно НО. На большом размере данных(в моём случае это 10 миллионов символов A, которые нужно заменить на BB) программа работает достаточно долго, на сколько я понимаю, нормальный алогоритм должен отрабатывать менее, чем за секунду, мой же отрабатывает примерно за 6.3 секунды. Подскажите, пожалуйста, как в моём случае можно ускорить работу программы.

Входные данные берутся из текстового документа input.txt, результат записывается в output.txt. Данные нужно получать построчно(такое условие задачи).

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <iostream>
#include <string>
#include <fstream>
#include <optional>
#include <ctime>
#include <algorithm>
 
 
struct Args
{
    std::string inputFileName;
    std::string outputFileName;
    std::string searchString;
    std::string replaceString;
};
 
std::optional<Args> ParseArgs(int argc, char* argv[])
{
    if (argc != 5)
    {
        std::cout << "Invalid arguments count" << std::endl;
        std::cout << "Usage: replace.exe <input file name> <output file name> <search string> <replace string>" << std::endl;
        return std::nullopt;
    }
 
    Args args;
    args.inputFileName = argv[1];
    args.outputFileName = argv[2];
    args.searchString = argv[3];
    args.replaceString = argv[4];
    return args;
}
 
void ReplaceString(std::string& stringForReplace, const std::string& searchString, const std::string& replaceString)
{
 
    size_t searchStringSize = searchString.length();
    size_t replaceStringSize = replaceString.length();
 
    for (size_t indexChar = stringForReplace.find(searchString); indexChar != std::string::npos;)
    {
        stringForReplace.erase(indexChar, searchStringSize);
        stringForReplace.insert(indexChar, replaceString);
        indexChar = stringForReplace.find(searchString, indexChar + replaceStringSize);
    }
 
}
bool CheckFiles(std::ifstream& input, std::fstream& output, std::optional<Args> args)
{
    input.open(args->inputFileName);
    if (!input.is_open())
    {
        std::cout << "Failed to open '" << args->inputFileName << "' for reading." << std::endl;
        return false;
    }
 
    output.open(args->outputFileName);
    if (!output.is_open())
    {
        std::cout << "Failed to open '" << args->outputFileName << "' for writing." << std::endl;
        return false;
    }
    return true;
}
 
void Replace(std::ifstream& input, std::fstream& output, const std::optional<Args>& args)
{
    std::string stringForReplace;
    while (std::getline(input, stringForReplace))
    {
        if (stringForReplace.size() >= args->searchString.size())
        {
            ReplaceString(stringForReplace, args->searchString, args->replaceString);
            output << stringForReplace << std::endl;
        }
    }
}
 
int main(int argc, char* argv[])
{
    auto args = ParseArgs(argc, argv);
    if (!args.has_value())
    {
        return 1;
    }
 
    std::ifstream input;
    std::fstream output;
    if (!CheckFiles(input, output, args))
    {
        return 1;
    }
    Replace(input, output, args);
    std::cout << "runtime = " << clock() / 1000.0 << std::endl;
    return 0;
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
14.02.2022, 19:31
Ответы с готовыми решениями:

Функция замены всех вхождений подстроки
Необходимо написать функцию типа функции PHP str_replace , которая возвращает строку, в которой все вхождения search заменены на replace....

Составьте правило замены в строке А всех вхождений строки В на строку С.  
Составьте правило замены в строке А всех вхождений строки В на строку С.

Найти количество всех вхождений заданной подстроки в заданной строке
Найти количество всех вхождений заданной подстроки в заданной строке (порядок следования символов важен, но символы подстроки в исходной...

26
 Аватар для igorrr37
2897 / 2044 / 992
Регистрация: 21.12.2010
Сообщений: 3,793
Записей в блоге: 9
15.02.2022, 10:45
Лучший ответ Сообщение было отмечено Lekopor как решение

Решение

Студворк — интернет-сервис помощи студентам
вот для случая когда подстрока которую надо заменить состоит из одного символа (для более длинных надо дорабатывать)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <functional>
#include <iterator>
#include <ctime>
 
// char str1[] = "AsdAsdAs";
// char str2[] = "BBsdBBsdBBs";
 
int main()
{
    std::fstream ifs{ "in.txt", std::ios::in | std::ios::binary }, ofs{"out.txt", std::ios::out | std::ios::binary}; // входной и выходной файлы
    if (!(ifs.is_open() && ofs.is_open()))
    {
        std::cerr << "Unable to open files\n";
        return 1;
    }
    char const* s1 = "A", *s2 = "BB"; // начальная и конечная подстроки (начальная должна состоять из одного символа)
    int s1l = strlen(s1);
    int s2l = strlen(s2);
    int coef = s2l / s1l + 1; 
    int len1 = 1000 * 1024, len2 = coef * len1;
    char* pb1 = new char[len1]; // входной буфер
    char* pb2 = new char[len2]; // выходной буфер
    while (true)
    {
        ifs.read(pb1, len1);
        int cread = ifs.gcount();
        if (cread != len1)
        {
            pb1[cread] = 0;
        }
        char* pnext = nullptr, *pprev = pb1, *pdest = pb2;
        for ( ; pnext = strstr(pprev, s1); pprev = pnext + s1l)
        {
            strncpy(pdest, pprev, pnext - pprev);
            pdest += pnext - pprev;
            strcpy(pdest, s2);
            pdest += s2l;
        }
        pnext = pb1 + cread;
        strncpy(pdest, pprev, pnext - pprev);
        pdest += pnext - pprev;
        int cwrite = pdest - pb2;
        ofs.write(pb2, cwrite);
 
        bool fff = ifs.fail();
        bool eee = ifs.eof();
        if (fff || eee)
        {
            break;
        }
    }
 
 
    delete[] pb1;
    pb1 = nullptr;
    delete[] pb2;
    pb2 = nullptr;
    ifs.close();
    ofs.close();
    std::cout << "runtime = " << clock() / 1000.0 << std::endl;
}
0
0 / 0 / 0
Регистрация: 14.02.2022
Сообщений: 12
15.02.2022, 12:44  [ТС]
Да, так уже сделал, заметил прирост на 50к строках, спасибо

Добавлено через 53 секунды
Kuzia domovenok, попробовал, странно, но стало даже медленнее
0
 Аватар для igorrr37
2897 / 2044 / 992
Регистрация: 21.12.2010
Сообщений: 3,793
Записей в блоге: 9
15.02.2022, 13:49
Lekopor, а какой у тебя сейчас лучший результат? У меня прога делает замену А на ВВ с количеством замен 41млн за время 0.75с
0
0 / 0 / 0
Регистрация: 14.02.2022
Сообщений: 12
15.02.2022, 14:15  [ТС]
igorrr37, Я пока что Ваш способ ещё не попробовал, разбираюсь в нём, лучшее время 10млн за 5.3
Я так понимаю, действительно читать нужно по-другому

Добавлено через 9 минут
igorrr37, сейчас запустил Ваш код, за 0.3 отрабатывает. Осталось понять что там и как, пока что тёмный лес, не понимаю, что там происходит и как это переделать для того, что бы заменять не 1 символ. но ещё раз большое спасибо!

Добавлено через 6 минут
Хотя как заменять не 1 символ уже понял
0
 Аватар для igorrr37
2897 / 2044 / 992
Регистрация: 21.12.2010
Сообщений: 3,793
Записей в блоге: 9
15.02.2022, 16:52
вот вроде любое кол-во меняет, надо тестировать.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <functional>
#include <iterator>
#include <ctime>
 
// char str1[] = "AsdAsdAs";
// char str2[] = "BBsdBBsdBBs";
 
int main()
{
    std::fstream ifs{ "in.txt", std::ios::in | std::ios::binary }, ofs{ "out.txt", std::ios::out | std::ios::binary }; // входной и выходной файлы
    if (!(ifs.is_open() && ofs.is_open()))
    {
        std::cerr << "Unable to open files\n";
        return 1;
    }
    char const* s1 = "AAA", * s2 = "BBBB"; // начальная и конечная подстроки 
    int s1len = strlen(s1);
    int s2len = strlen(s2);
    int coef = s2len / s1len + 1;
    int len1 = 1000*1024, len2 = coef * len1, ctail = 0;
    char* pb1 = new char[len1]; // входной буфер
    char* pb2 = new char[len2]; // выходной буфер
    while (true)
    {
        ifs.read(pb1 + ctail, len1 - ctail);
        int cread = ifs.gcount() + ctail;
        if (cread != len1)
        {
            pb1[cread] = 0;
        }
        char* pnext = nullptr, * pprev = pb1, * pdest = pb2;
        int ncopy = 0;
        for (; pnext = strstr(pprev, s1); pprev = pnext + s1len)
        {
            ncopy = pnext - pprev;
            strncpy(pdest, pprev, ncopy);
            pdest += ncopy;
            strcpy(pdest, s2);
            pdest += s2len;
        }
        pnext = pb1 + cread;
        ncopy = pnext - pprev;
        strncpy(pdest, pprev, ncopy);
        pdest += ncopy;
 
        ctail = pnext - pprev;
        if (ctail >= s1len)
        {
            ctail = s1len - 1;
        }
 
        int cwrite = pdest - pb2;
        if (cread == len1)
        {
            cwrite -= ctail;
        }
        ofs.write(pb2, cwrite);
 
        memmove(pb1, pb1 + len1 - ctail, ctail);
 
        bool fff = ifs.fail();
        bool eee = ifs.eof();
        if (fff || eee)
        {
            break;
        }
    }
 
    delete[] pb1;
    pb1 = nullptr;
    delete[] pb2;
    pb2 = nullptr;
    ifs.close();
    ofs.close();
    std::cout << "runtime = " << clock() / 1000.0 << std::endl;
}
0
0 / 0 / 0
Регистрация: 14.02.2022
Сообщений: 12
15.02.2022, 16:54  [ТС]
У меня получилось менять любое количество, я передаю в s1 аргументом подстроку. Я в целом сейчас пытаюсь разобраться в коде, для меня такой формат работы с файлом в новинку
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
15.02.2022, 21:14
Lekopor, то что вам советует , igorrr37 , похоже на правду. но настолько же и далекое.
Это все явно не С++
Мож вам уединится в другой ветке ?

Добавлено через 48 секунд
igorrr37, все что вы делаете абсолютно излишние телодвижения
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.02.2022, 21:14

Поиск всех вхождений подстроки
Написать в int main() код, который будет выводить на экран результат (res) функции поиска, но чтобы выводило все знач #include...

Замена всех вхождений подстроки
Здравствуйте, у меня получилось написать следующее: str_repl('', _, _, ''):-!. str_repl(String, SubString, Replace, Res):- ...

Количество вхождений подстроки в строке
Как это реализовать с помощью регулярных выражений? Допустим есть текст: Я сделал следующее: open INPUT, &quot;&lt; 1.txt&quot; ...

Поиск всех вхождений подстроки в строку
Здравствуйте, помогите пожалуйста со следующей задачей. Имеется переменная, в которую загружен достаточно длинный текст. Мне нужно найти...

Подсчитать количество вхождений подстроки в строке
Вот функция function CntRecurrences(substr, str: string): integer; var cnt, p: integer; begin cnt := 0; while str...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
27
Ответ Создать тему
Новые блоги и статьи
Теория всего 12. ВГК
anaschu 21.07.2026
### Главные семантические изменения и дешифровка новой физики 1. **`REPRODUCTIVE_EMISSION` вместо фотосинтеза (`PS_base`)**: Энергия и ресурсы, которые класс средних мужчин (`_W_MEN_DONORS`). . .
Публикация отклонённая на хабре. Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование задачи и целеполагание
Hrethgir 21.07.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11948&stc=1&d=1784657928 Привет Хабр. В этой статье я расскажу, как один закон эпистемологии позволил мне с ходу запустить уникальный. . .
Теория всего 11. Основные параметры
anaschu 21.07.2026
Дешифровка тензорного ядра Soil Chemistry 2. 0: Истинный инвариант Теории Всего Чистовой исходный код многокомпонентной сукцессии зафиксирован. Модель оперирует единым вектором состояния. . .
Теория всего 10. Клод трусишка
anaschu 21.07.2026
Алгоритмический суицид ИИ: Когда математика ОДУ взламывает цензурные шлюзы Свежайший мета-прецедент нашей разработки! Клод официально отказался строить итоговую кроссплатформенную модель, как. . .
Теория всего 9. Окончательная проработка метафоры "дерево = традиции"
anaschu 21.07.2026
Скрытые параметры ядра ОДУ: Механика Глубинного Рока Клод утаил от вас ключевую математику кризисов. В движке игры зашиты пять скрытых коэффициентов, определяющих, как именно ТНК и Мемы ломают. . .
Теория всего 8. Clauude трусишка. Ответ джемени
anaschu 21.07.2026
Игровой баланс «Модели Всего»: Алгоритмический блок как механика Семантического БуфераЭтот скриншот отказа Клода — идеальный, чистейший прецедент для нашей Теории Всего. Вы столкнулись не просто с. . .
Теория всего 7. Дерево - это патриархат, грибы - это феминизм
anaschu 21.07.2026
Уничтожение Патриархата: Как ТНК, Мемы и Половой отбор зачистили «Сексуальный Пролетариат» Величайшая иллюзия современного человека — вера в «свободу воли», «социальный прогресс» и «эволюцию. . .
История и социология Терры на примере борьбы микориз за пространство. 1. Глоссарий терры.
anaschu 21.07.2026
Решил тут подумать о возможности сделать лор некоторой комп игры - стратегии, или худжественной книги антиутопии, которые будут юзать планету,которая максимально будет похожа на нашу землю, но где. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru