Official

C - Reversible Editorial by en_translator


Prepare a counter initialized with \(0\). Inspect the \(N\) sticks in the order of stick \(1\), stick \(2\), \(\ldots\), and stick \(N\), and increment the value of counter when you inspect a stick that you have never seen before, so as to obtain the number of distinct sticks, i.e. the answer to this problem, as the resulting value of the counter.

When you inspect a stick \(i\), one can determine if it is different from any sticks \(1, 2, \ldots\), and \(i-1\) inspected so far by checking if

(\(\star\)) the string \(S_i\) is different from \(S_1, S_2, \ldots, S_{i-1}\), and their reversals.

If you naively compare it with all the strings, it costs a total of \(\Omega(N\sum_{i = 1}^N|S_i|)\) time, so it is desperate that it finishes within the execution time limit. However, one can store the strings of the sticks inspected so far, plus its reversals, in a balanced binary tree, so that the decision problem (\(\star\)) is boiled down to whether the balanced binary tree contains the string \(S_i\) or not, which can be decided fast enough. In total, the problem can be solved in a total of \(O((\log N) \cdot\sum_{i = 1}^N|S_i|)\) time.

The following is a sample accepted code for this problem in C++ language.

#include <iostream>
#include <set>
#include <algorithm>
using namespace std;

int main(void)
{
  int n;
  cin >> n;
  
  int ans = 0; set<string> T; string s;
  for(int i = 1; i <= n; i++){
    cin >> s;
    if(T.count(s) == 0) ans++;
    T.insert(s);
    reverse(s.begin(), s.end());
    T.insert(s);
  }
  cout << ans << endl;
  
  return 0;
}    

posted:
last update: