#include <iostream>
#include <cmath>
using namespace std;
/*
Существенная часть задачи
Исходя из условий, я понял, что фамилии похожи, если они:
1) Различаются по длине не более, чем на 1 букву
2) Отличаются только последней буквой
Здесть важное уточнение: мой алгоритм считает, что "ааб" и "аав" - похожие.
Из задания не ясно, похожи они, или нет
*/
bool isSimilar(string left, string right, size_t diff_chars = 1) {
auto a = left.begin();
auto b = right.begin();
// Отсекаем фамилии, которые сильно отличаются по длине.
// Они точно не будут похожими
size_t diff = abs((int)left.length() - (int)right.length());
if (diff > diff_chars) {
return false;
}
size_t similar_chars = 0;
// Пробегаем по строкам посимвольно, пока символы равны.
// Попутно увеличивая переменную `similar_chars`
for(;a != left.end() && b != right.end(); a++, b++, similar_chars++) {
if (*a != *b) {
break;
}
}
// Если количество одинаковых символов отличается
// от длины самой длинной фамилии не более чем на `diff_chars`,
// то они похожи. Если нет, то не похожи
auto length = max(left.length(), right.length());
return ((length - similar_chars) <= diff_chars);
}
/* Структура для хранения информации о человеке - фамилия и возраст */
struct Person{
string name; // Я назвал поле `name`, а не `last_name`, но думаю, что это не принципиально
uint age;
/*
Перегружаем оператор сравнения для удобства.
В рамках этой задачи можно считать, что два объекта `Person`
будут равны, если их фамилии похожи.
Теперь можно писать `p == q` вместо `isSimilar(p.name, q.name)`
*/
bool operator ==(const Person& other) const {
return isSimilar(this->name, other.name);
}
// Здесь я перегружаю операторы ввода-вывода просто для удобства.
friend ostream& operator<<(ostream& os, const Person& obj) {
os << obj.name << " (" << obj.age << " y/o)";
return os;
}
friend istream& operator>>(istream& is, Person& obj) {
is >> obj.name >> obj.age;
return is;
}
};
int main(int argc, char** argv) {
//Читаем количество людей, которое будет вводить пользователь
int c;
cin >> c;
//Создаем массив, чтобы их хранить (см. `struct Person` выше)
auto p = new Person[c];
//Читаем
for(auto i = 0; i < c; i++) {
cin >> p[i];
}
//Сравниваем людей "каждый с каждым", чтобы найти похожих
for(auto i = 0; i < c; i++) {
for(auto j = i+1; j < c; j++) { //здесь j = i+1 чтобы не сравнивать с самим собой
if (p[i] == p[j]) { // оператор "==" здесь НЕ означет "равно", см. перегруженный оператор в `Person`
cout << p[i] << " ~= " << p[j] << endl; // Если похожи - выводим на экран
}
}
}
/*Подчищаем за собой*/
delete[] p;
return EXIT_SUCCESS;
}