1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
#ifndef LOCAL
#pragma GCC optimize ("O3")
#endif

#include <bits/stdc++.h>

using namespace std;

#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return {i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (c it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(x...) " [" #x ": " << (x) << "] "

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
template <typename A, typename B>
using unordered_map2 = __gnu_pbds::gp_hash_table<A, B>;
using namespace __gnu_pbds;
template <typename T> using ordered_set =
  __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag,
                   __gnu_pbds::tree_order_statistics_node_update>;
// ordered_set<int> s; s.insert(1); s.insert(2);
// s.order_of_key(1);    // Out: 0.
// *s.find_by_order(1);  // Out: 2.

using ld = long double;
using ll = long long;

constexpr int Ile = 4;
constexpr int mod[Ile] = {1000 * 1000 * 1000 + 7,
                          1000 * 1000 * 1000 + 9,
                          1000 * 1000 * 1000 + 21,
                          1000 * 1000 * 1000 + 33};
constexpr int pier[Ile] = {5003, 5009, 5011, 5021};

ll przod[Ile] = {0, 0, 0, 0};
ll tyl[Ile] = {0, 0, 0, 0};
ll pot[Ile] = {1, 1, 1, 1};

void DodajZnak(char c) {
  debug() << imie(c);
  #ifdef LOCAL
  assert('a' <= c and c <= 'z');
  #endif
  const int dig = c - 'a';
  assert(0 <= dig and dig <= 30);
  #define KROK(i) do {                               \
    przod[i] = (przod[i] * pier[i] + dig) % mod[i];  \
    tyl[i] = (tyl[i] + pot[i] * dig) % mod[i];       \
    pot[i] = (pot[i] * pier[i]) % mod[i];            \
  } while (0)
  KROK(0);
  KROK(1);
  KROK(2);
  KROK(3);
  assert(Ile == 4);
}

bool Rowne() {
  for (int i = 0; i < Ile; i++) {
    if (przod[i] != tyl[i]) {
      return false;
    }
  }
  return true;
}

int main() {
  while (getchar_unlocked() != '\n');
  while (true) {
    const int znak = getchar_unlocked();
    if (znak == '\n') break;
    if (znak == EOF) break;
    DodajZnak(znak);
  }
  cout << (Rowne() ? "TAK" : "NIE") << endl;
  return 0;
}