#c #arrays #string #vector #character
#c #массивы #строка #вектор #символ
Вопрос:
Я хочу принимать входные данные от пользователя определенным образом, например, следующим образом :
L1 L2 L3 N
L1, L2, L3 — это строки, разделенные пробелами. А N — целое число. Я пытался использовать cin
, но это было медленно. Мне нужно быстро получить ввод. Также строка L2 повторяется N раз. Поэтому я должен хранить l1 l2*N l3
. Я пробовал string, но он становится слишком медленным. Я получаю TLE.
Вот как я их сохранил :
#include<bits/stdc .h>
using namespace std;
int main (){
string l1,l2,l3;
int n;
cin>>l1>>l2>>l3>>n;
string r;
r.reserve(l1.size() n * l2.size() l3.size());
r = l1;
for (int i=0; i<n;i )
r =l2;
r = l3;
cout<<r<<endl;
return 0;
}
And then iterated it in 2 separate for loops with maximum 1000 iterations in each loop.
Как я могу эффективно их хранить? Я знаю о векторах, но я в них не силен. Итак, если кто-нибудь знает, как сохранить их в этой последовательности в векторе, пожалуйста, помогите мне. Или, если они могут быть сохранены в массиве символов, то как это сделать?
Комментарии:
1. Вы уверены, что именно ввод замедляет вас, а не ваш алгоритм?
2. Я сомневаюсь, что это
cin
слишком медленно, скорее всего, это текущий метод, который у вас есть для чтения в строках. Разделены ли строки пробелом L2 * N или они объединены вместе (так что технически это только одна длинная строка)? Ответ на то, как вы должны их хранить, полностью зависит от того, для чего вы хотите использовать строки впоследствии.3. Да, я так думаю, потому что все, что я делал в остальной части кода, это повторял строку, т.е.
(l1 l2*n l3)
в 2 отдельныхfor loop
, которые выполнялись бы в худшем случае 1000 раз.4. Как насчет того, чтобы вы показали нам конкретный пример формата ввода и соответствующие части вашего текущего кода для его чтения?
5.
for (int i=0; i<n;i ) r =l2;
предстоит проделать большую работу. особенно, если вы делаете это в некоторых вложенных циклах for до 1 000 000 раз.
Ответ №1:
Хорошо. Итак, давайте начнем с выделения фактического чтения из другого кода:
struct foo {
std::string l1, l2, l3;
int n;
friend std::istream amp;operator>>(std::istream amp;is, foo amp;f) {
return is >> f.l1, >> f.l2 >> f.l3 >> n;
}
};
С помощью этого мы можем читать в файле, полном этих записей, в вектор с чем-то вроде этого:
std::vector<foo> data { std::istream_iterator<foo>(infile), {} };
Я бы предположил, что это (само по себе) не будет узким местом. Вероятно, есть более быстрые способы выполнить работу, если это действительно необходимо, но я сомневаюсь, что это действительно необходимо.
Основываясь на комментариях о том, как должен выполняться поиск, мы можем выполнять поиск, даже не расширяя вторую строку до n
вхождений l2
.
Поиск выполняется для одного символа от начала строки до последнего (самого правого) появления какого-либо другого символа.
Поскольку этот шаблон «end» представляет собой один символ, мы можем сделать это довольно легко, вообще не расширяя среднюю строку ( L2
). Логика в основном:
if L3 contains end_pattern
total = count(L1) count(L2) * n count(L3.substr(0, pattern_pos))
else if L2 contains end_pattern
total = count(L1) count(L2) * (n-1) count(L2.substr(0, pattern_pos))
else if L1 contains end_pattern
total = count(L1.substr(0, pattern_pos))
else
total = 0; // pattern isn't present anywhere
По крайней мере, как описано в комментариях, похоже, нет необходимости в алгоритме O (N 2), описанном в комментариях.
Комментарии:
1. Спасибо за помощь. И для части поиска предположим, что если у меня есть этот ввод
aabba bbba aaaa 2
сейчас, я хочу вычислить ни одного из a после первого b с правой стороны. Можно ли это сделать без использования конкатенации l2 n раз?2. @samthornton: Что означает «после первого B с правой стороны»?
3. Я имею в виду, что я хочу не вычислять ни одного а с правой стороны, но только после обнаружения хотя бы 1 b, иначе счетчик будет равен нулю. Например
ba ab aa 4
, это ввод, затем он становитсяba abababab aa
(игнорируйте пробелы) теперь я хочу вычислить количество а с правой стороны, т.е.index = string.size() -1
Но только после того, как я столкнусь с одним b. То есть я буду.итерации с правой стороны, и после просмотра одного b я буду считать число a. Здесь число a после первого b с правой стороны5
.4. Я также разработал ту же схему. Я понял, насколько глупо было спрашивать об этом. Спасибо за ваше время и усилия.