Задание было предложено на тесте в комании Яндекс.
Дана последовательность строк.
Нужно для каждой строки сформировать сокращение.
Сокращение представляет собой строку, в которой
есть префикс и суффикс одинаковой длины (которые берутся из строки)
остальная часть строки заменяется на число (количество заменённых символов)
Например, для строки aaaaaaa
возможны сокращения a5a
или aa3aa
или aaa1aaa
.
Необходимо для всех полученных строк сформировать сокращения, причём каждое сокращение должно быть уникальным. Если сформировать скоращение невозможно, необходимо вернуть исходную строку.
Входные данные:
2
localization
internationalization
Результат:
l10n
i18n
Входные данные:
10
aaaa
abaa
abab
bbbb
baba
aaaaaaaaaaaaaaaaaaaa
abaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbb
sjfdhlsakdjfhsald
sdfasdfsadfafdsfdd
Результат:
aaaa
abaa
a2b
b2b
b2a
aa16aa
ab16aa
b18b
s15d
s16d
#include <iostream>
#include <string>
#include <map>
#include <unordered_map>
#include <vector>
#include <stack>
#include <set>
#include <algorithm> // std::sort
#include <queue>
using namespace std;
struct abbrItem {
string origin; // исходная строчка
string abbr; // сокращенная
int index; // индекс элемента
int possible_len; // макс.возможная длину префикса для сокращения
bool completed; // отмечает, завершена ли обработка строки
bool marked; // если true, запись отмечена, как конфликтная, и направлена в stack conflicts
};
class Solution {
private:
queue <int> conflicts; // очередь для урегулирования конфликтов
vector <abbrItem> out;
map <string, int> abbrmap; // карта сокращений, второй параметр -- индекс в out
int iteration; // текущая итерация по формированию сокращений
void inputStrings(vector <string> &s);
string getAbbr(string s, int l);
void resolveConflicts();
void genAbbr(int i); // генерация сокращения
public:
void Input();
void Run();
void Print();
};
void Solution::Input()
{
string one;
vector <string> s;
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> one;
s.push_back( one ); // запоминаем исходную строчку в векторе
}
inputStrings(s);
}
void Solution::Print()
{
for(auto x : out) {
cout << x.abbr << endl;
}
}
string Solution::getAbbr(string s, int l)
{
string x;
int len = s.length(), n;
if(l <= 0 || l*2 >= len) {
x = s;
} else {
n = len - l*2;
x = s.substr(0,l) + to_string(n) + s.substr(l+n,l);
}
return x;
}
void Solution::resolveConflicts()
{
int index;
vector<int> v;
while (conflicts.empty() == false) {
iteration += 1;
abbrmap.clear();
// переписываем conflicts в v
// одновременно снимаем метку marked
while (conflicts.empty() == false) {
index = conflicts.front();
v.push_back(index);
conflicts.pop();
out[index].marked = false;
}
// теперь conflicts -- пустой
// проходим по вектору, для каждого индекса генерим новое сокращение
for(auto i : v) {
genAbbr(i);
}
}
}
void Solution::genAbbr(int i)
{
string s;
map <string, int>::iterator it;
abbrItem item;
if(iteration > out[i].possible_len) {
// сокращение невозможно
out[i].abbr = out[i].origin;
} else {
// сокращение возможно
s = getAbbr(out[i].origin, iteration);
out[i].abbr = s;
if ((it = abbrmap.find(s)) == abbrmap.end()) {
// сокращения нет в карте, добавляем
abbrmap[s] = i;
} else {
// конфликт, помечаем, позже будем регулировать
item = out[ it->second ];
if(item.marked == false) {
item.marked = true;
conflicts.push( item.index );
}
out[ it->second ] = item;
if(out[i].marked == false) {
out[i].marked = true;
conflicts.push( i );
}
}
}
}
void Solution::Run()
{
// проход по массиву, осуществляем сокращения
// запоминаем сокращения в карте abbrmap
// если есть конфликты, они отправляются в очередь
// позже будем регулировать конфликты
iteration = 1;
for(int i = 0; i < (int)out.size(); i++) {
out[i].marked = false;
genAbbr(i);
}
// если есть конфликты, они будут в стеке conflicts
resolveConflicts();
}
void Solution::inputStrings(vector <string> &s)
{
abbrItem item;
int len;
int i = 0;
for(auto x : s) {
item.index = i;
item.origin = x;
item.abbr = x;
len = x.length();
item.possible_len = len < 3 ? 0: len / 2 - 1;
out.push_back(item);
i++;
}
}
int main()
{
Solution s;
s.Input();
s.Run();
s.Print();
return 0;
}