fork download
  1. #include <iostream>
  2. #include <cmath>
  3.  
  4. using namespace std;
  5.  
  6.  
  7. /*
  8. Существенная часть задачи
  9.  
  10. Исходя из условий, я понял, что фамилии похожи, если они:
  11. 1) Различаются по длине не более, чем на 1 букву
  12. 2) Отличаются только последней буквой
  13.  
  14. Здесть важное уточнение: мой алгоритм считает, что "ааб" и "аав" - похожие.
  15. Из задания не ясно, похожи они, или нет
  16.  
  17. */
  18. bool isSimilar(string left, string right, size_t diff_chars = 1) {
  19.  
  20. auto a = left.begin();
  21. auto b = right.begin();
  22.  
  23. // Отсекаем фамилии, которые сильно отличаются по длине.
  24. // Они точно не будут похожими
  25. size_t diff = abs((int)left.length() - (int)right.length());
  26. if (diff > diff_chars) {
  27. return false;
  28. }
  29.  
  30. size_t similar_chars = 0;
  31. // Пробегаем по строкам посимвольно, пока символы равны.
  32. // Попутно увеличивая переменную `similar_chars`
  33. for(;a != left.end() && b != right.end(); a++, b++, similar_chars++) {
  34. if (*a != *b) {
  35. break;
  36. }
  37. }
  38.  
  39. // Если количество одинаковых символов отличается
  40. // от длины самой длинной фамилии не более чем на `diff_chars`,
  41. // то они похожи. Если нет, то не похожи
  42. auto length = max(left.length(), right.length());
  43. return ((length - similar_chars) <= diff_chars);
  44. }
  45.  
  46.  
  47. /* Структура для хранения информации о человеке - фамилия и возраст */
  48. struct Person{
  49. string name; // Я назвал поле `name`, а не `last_name`, но думаю, что это не принципиально
  50. uint age;
  51.  
  52. /*
  53. Перегружаем оператор сравнения для удобства.
  54. В рамках этой задачи можно считать, что два объекта `Person`
  55. будут равны, если их фамилии похожи.
  56.  
  57. Теперь можно писать `p == q` вместо `isSimilar(p.name, q.name)`
  58. */
  59. bool operator ==(const Person& other) const {
  60. return isSimilar(this->name, other.name);
  61. }
  62.  
  63. // Здесь я перегружаю операторы ввода-вывода просто для удобства.
  64. friend ostream& operator<<(ostream& os, const Person& obj) {
  65. os << obj.name << " (" << obj.age << " y/o)";
  66. return os;
  67. }
  68.  
  69. friend istream& operator>>(istream& is, Person& obj) {
  70. is >> obj.name >> obj.age;
  71. return is;
  72. }
  73. };
  74.  
  75.  
  76. int main(int argc, char** argv) {
  77. //Читаем количество людей, которое будет вводить пользователь
  78. int c;
  79. cin >> c;
  80.  
  81. //Создаем массив, чтобы их хранить (см. `struct Person` выше)
  82. auto p = new Person[c];
  83. //Читаем
  84. for(auto i = 0; i < c; i++) {
  85. cin >> p[i];
  86. }
  87.  
  88. //Сравниваем людей "каждый с каждым", чтобы найти похожих
  89. for(auto i = 0; i < c; i++) {
  90. for(auto j = i+1; j < c; j++) { //здесь j = i+1 чтобы не сравнивать с самим собой
  91. if (p[i] == p[j]) { // оператор "==" здесь НЕ означет "равно", см. перегруженный оператор в `Person`
  92. cout << p[i] << " ~= " << p[j] << endl; // Если похожи - выводим на экран
  93. }
  94. }
  95. }
  96.  
  97. /*Подчищаем за собой*/
  98. delete[] p;
  99. return EXIT_SUCCESS;
  100. }
Success #stdin #stdout 0s 3420KB
stdin
10
Ivanov 23
Petrov 56
Ivanova 78
Sidorov 4
Smirnova 40
Smirnov 81
Morozova 11
Medvedev 56
Morozov 19
Ivanov 45
stdout
Ivanov (23 y/o) ~= Ivanova (78 y/o)
Ivanov (23 y/o) ~= Ivanov (45 y/o)
Ivanova (78 y/o) ~= Ivanov (45 y/o)
Smirnova (40 y/o) ~= Smirnov (81 y/o)
Morozova (11 y/o) ~= Morozov (19 y/o)