// includes {{{
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<cmath>
#include<random>
#include<cassert>
// #include<deque>
// #include<multiset>
// #include<bitset>
// #include<cstring>
// #include<bits/stdc++.h>
// }}}
using namespace std;
using ll = long long;

// #undef DEBUG
// #define DEBUG
// DEBUG {{{
#include <array>
#include <deque>
#include <list>
#include <ostream>
#include <queue>
#include <stack>
#include <tuple>
#include <valarray>
#include <vector>
template < int n, class... T >
typename enable_if< (n >= sizeof...(T)) >::type __output_tuple(ostream &,
    tuple< T... > const &) {}
template < int n, class... T >
typename enable_if< (n < sizeof...(T)) >::type __output_tuple(ostream &os,
    tuple< T... > const &t) {
  os << (n == 0 ? "" : ", ") << get< n >(t);
  __output_tuple< n + 1 >(os, t);
}
template < class... T >
ostream &operator<<(ostream &os, tuple< T... > const &t) {
  os << "(";
  __output_tuple< 0 >(os, t);
  os << ")";
  return os;
}
template < class T, class U >
ostream &operator<<(ostream &os, pair< T, U > const &p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}
template < class T >
ostream &operator<<(ostream &os, const stack< T > &a) {
  os << "{";
  for(auto tmp = a; tmp.size(); tmp.pop())
    os << (a.size() == tmp.size() ? "" : ", ") << tmp.top();
  os << "}";
  return os;
}
template < class T, class Container, class Compare >
ostream &operator<<(ostream &os, priority_queue< T, Container, Compare > a) {
  os << "{ (top) ";
  while(a.size()) os << a.top() << (a.size() == 1 ? "" : ", "), a.pop();
  os << " }";
  return os;
}
template < class T, class Container >
ostream &operator<<(ostream &os, queue< T, Container > a) {
  os << "{ ";
  while(a.size()) os << a.front() << (a.size() == 1 ? "" : ", "), a.pop();
  os << " }";
  return os;
}
#ifdef DEBUG
#if !defined(DEBUG_OUT)
#define DEBUG_OUT cerr
#endif
#define dump(...)                                                                \
  [&]() {                                                                        \
    auto __debug_tap = make_tuple(__VA_ARGS__);                                  \
    DEBUG_OUT << "[" << __LINE__ << "] " << #__VA_ARGS__ << " = " << __debug_tap \
    << endl;                                                           \
  }()
template < class T >
inline void dump2D(T &d, size_t sizey, size_t sizex) {
  for(size_t i = 0; i < sizey; i++) {
    DEBUG_OUT << "\t";
    for(size_t j = 0; j < sizex; j++)
      DEBUG_OUT << d[i][j] << (j + 1 == sizex ? "" : "\t");
    DEBUG_OUT << endl;
  }
}
template < class T >
inline void dump1D(T &d, size_t sizey) {
  for(size_t i = 0; i < sizey; i++) {
    DEBUG_OUT << d[i] << (i + 1 == sizey ? "" : " ");
  }
  DEBUG_OUT << endl;
}
template < class T, class = typename iterator_traits< decltype(begin(T())) >::value_type,
         class = typename enable_if< !is_same< T, string >::value >::type >
         ostream &operator<<(ostream &os, const T &a) {
           os << "{";
           for(auto ite = begin(a); ite != end(a); ++ite)
             os << (ite == begin(a) ? "" : ", ") << *ite;
           os << "}";
           return os;
         }
#else
#define dump(...) (42)
#define dump2D(...) (42)
#define dump1D(...) (42)
template < class T, class = typename iterator_traits< decltype(begin(T())) >::value_type,
         class = typename enable_if< !is_same< T, string >::value >::type >
         ostream &operator<<(ostream &os, const T &a) {
           for(auto ite = begin(a); ite != end(a); ++ite)
             os << (ite == begin(a) ? "" : " ") << *ite;
           return os;
         }
#endif
// }}}


// [i] = size of longest common suffix and prefix in s[0,i-1]
// momentary O(log N)
// overall O(N)
// KMP {{{

#include <string>
#include <vector>

template < class T >
vector< int > KMP(T s) {
  int n = s.size();
  vector< int > kmp(n + 1), mp(n + 1);
  kmp[0] = mp[0] = -1;
  int j = -1;
  for(int i = 0; i < n; i++) {
    while(j >= 0 && s[i] != s[j]) j = kmp[j];
    kmp[i + 1] = mp[i + 1] = ++j;
    if(i + 1 < n && s[i + 1] == s[j]) kmp[i + 1] = kmp[j];
  }
  return mp;
}

// }}}


// require kmp
// [i] = min cycle length in [0,i]
// NOTE : not always JUST
// cycle {{{
#include <string>
#include <vector>

template < class T >
vector< int > cycle(T s) {
  auto mp = KMP(s);
  vector< int > len(s.size());
  for(int i = 0; i < (int) s.size(); i++) len[i] = i + 1 - mp[i + 1];
  return len;
}
// }}}


// mystring( <string-like> )
// .shift(ll n)
// .push_front(c)
// .changeAt(index, from, to)
// [ll index] -= , +=
/// --- HashString with rolling-hash {{{ ///

// #include <functional>
#include <iterator>
#include <string>
#include <vector>

template < int N, int mod, int* B, int SZ >
class HashString {
  static_assert(N >= 1, "N must be positive");

  class PowTable {
  public:
    int table[SZ][(N + 1) * 2 + 1];
    PowTable() {
      for(int i = 0; i < SZ; i++) {
        table[i][N] = 1;
        for(int j = 1; j <= N; j++) {
          table[i][j + N] = (ll) table[i][j - 1 + N] * B[i] % mod;
        }
        table[i][N - 1] = modinv(B[i]);
        for(int j = -2; j >= -N; j--) {
          table[i][j + N] = (ll) table[i][j + 1 + N] * table[i][N - 1] % mod;
        }
      }
    }
  };
  static PowTable table;

public:
  static int modpow(int x, ll y) {
    int r = 1;
    if(y < 0) y = -y, x = modinv(x);
    while(y) {
      if(y & 1) r = (ll) r * x % mod;
      x = (ll) x * x % mod;
      y >>= 1;
    }
    return r;
  }
  static int extgcd(int a, int b, int& x, int& y) {
    int d;
    return b == 0 ? (x = a < 0 ? -1 : 1, y = 0, a < 0 ? -a : a)
      : (d = extgcd(b, a % b, y, x), y -= a / b * x, d);
  }
  static int modinv(int a) {
    int x, y;
    extgcd(a, mod, x, y);
    if(x < mod) x += mod;
    return x;
  }

  int hashed[SZ] = {};

  HashString() {}
  HashString(const char* str) : HashString(str, str + char_traits< char >::length(str)) {}
  HashString(const string& str) : HashString(str.begin(), str.end()) {}
  template < class T >
    HashString(const vector< T >& v) : HashString(v.begin(), v.end()) {}

  template < class InputIter, class = typename iterator_traits< InputIter >::value_type >
    HashString(const InputIter& first, const InputIter& last) {
      for(int i = 0; i < SZ; i++) {
        ll tmp = 1;
        for(InputIter now = first; now != last; ++now, tmp = tmp * B[i] % mod) {
          hashed[i] = (hashed[i] + tmp * ll(*now) % mod) % mod;
        }
      }
    }

  class Accessor {
    const ll n;
    HashString& str;

  public:
    Accessor(ll n, HashString& str) : n(n), str(str) {}
    template < class T >
      void operator+=(T c) {
        for(ll i = 0; i < SZ; i++) {
          ll bn = -N <= n && n <= N ? table.table[i][n + N] : modpow(B[i], n);
          str.hashed[i] = (str.hashed[i] + bn * ll(c) % mod + mod) % mod;
        }
      }
    template < class T >
      void operator-=(T c) {
        *this += -ll(c);
      }
    void operator+=(const HashString& a) {
      for(ll i = 0; i < SZ; i++) {
        ll bn = -N <= n && n <= N ? table.table[i][n + N] : modpow(B[i], n);
        str.hashed[i] = (str.hashed[i] + bn * a.hashed[i] % mod + mod) % mod;
      }
    }
    void operator-=(const HashString& a) {
      for(ll i = 0; i < SZ; i++) {
        ll bn = -N <= n && n <= N ? table.table[i][n + N] : modpow(B[i], n);
        str.hashed[i] = (str.hashed[i] - bn * a.hashed[i] % mod + mod) % mod;
      }
    }
  };

  Accessor operator[](ll i) { return Accessor(i, *this); }

  void shift(ll n = 1) {
    for(int i = 0; i < SZ; i++) {
      ll bn = -N <= n && n <= N ? table.table[i][n + N] : modpow(B[i], n);
      hashed[i] = (ll) hashed[i] * bn % mod;
    }
  }

  bool operator==(const HashString& a) const {
    for(int i = 0; i < SZ; i++) {
      if(hashed[i] != a.hashed[i]) return 0;
    }
    return 1;
  }

  HashString& operator+=(const HashString& a) {
    for(int i = 0; i < SZ; i++) {
      hashed[i] += a.hashed[i];
      if(hashed[i] >= mod) hashed[i] -= mod;
    }
    return *this;
  }

  HashString& operator-=(const HashString& a) {
    for(int i = 0; i < SZ; i++) {
      hashed[i] += mod - a.hashed[i];
      if(hashed[i] >= mod) hashed[i] -= mod;
    }
    return *this;
  }

  HashString operator+(const HashString& a) const {
    HashString tmp = *this;
    tmp += a;
    return tmp;
  }

  HashString operator-(const HashString& a) const {
    HashString tmp = *this;
    tmp -= a;
    return tmp;
  }

  template < class T >
    void push_front(const T& a) {
      for(int i = 0; i < SZ; i++) {
        hashed[i] = (ll) hashed[i] * B[i] % mod;
        hashed[i] = (hashed[i] + ll(a)) % mod;
      }
    }

  template < class T >
    void changeAt(ll n, T a, T b) {
      for(int i = 0; i < SZ; i++) {
        ll bn = -N <= n && n <= N ? table.table[i][n + N] : modpow(B[i], n);
        hashed[i] = (hashed[i] + (mod + ll(b) - ll(a)) * bn % mod) % mod;
      }
    }

  friend ostream& operator<<(ostream& os, const HashString& a) {
    // HASH_STRING{, }
    os << "HASH_STRING{" << a.hashed[0];
    for(int i = 1; i < SZ; i++) {
      os << ", " << a.hashed[i];
    }
    os << "}";
    return os;
  }
};
template < int N, int mod, int* B, int SZ >
typename HashString< N, mod, B, SZ >::PowTable HashString< N, mod, B, SZ >::table;

constexpr int _hs_N = 1e6;

int _hs_B[] = {
  114514,
  1919,
  810810,
};

using mystring =
HashString< _hs_N, 1'000'000'007, _hs_B, sizeof(_hs_B) / sizeof(_hs_B[0]) >;

namespace std {
  template < int N, int mod, int* B, int SZ >
    struct hash< HashString< N, mod, B, SZ > > {
      template < class T >
        static void hash_combine(size_t& seed, T const& v) {
          seed ^= hash< T >{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        }
      size_t operator()(const HashString< N, mod, B, SZ >& a) {
        size_t seed = 0;
        for(int i = 0; i < SZ; i++) {
          hash_combine(seed, a.hashed[i]);
        }
        return seed;
      }
    };
} // namespace std

/// }}}--- ///


int n;
string t;
int ans, ans2;

void check(string u) {
  if(u.size() % 2 == 1) return;
  int m = u.size() / 2;
  for(int i = m+1, j = m-1; i < u.size(); i++, j--) {
    if(u[i] != u[j]) return;
  }
  ans = min<int>(ans, (u.size() + 2) / 2);
  ans2 = min<int>(ans2, (u.size() + 2) / 2);
}

void check2(string u) {
  if(u.size() <= 3) return;
  mystring ms(u.substr(1, u.size() - 1));
  int len1 = u.size() - 1;
  // dump(u.substr(1, u.size() - 1));
  int len2 = 0;
  mystring g;
  int n = u.size();
  for(int i = 0; i < n - 1; i++) {
    g.push_front(u[i]);
    len2++;
    ms.changeAt(0, u[i+1], char(0));
    ms.shift(-1);
    len1--;
    while(len2 > len1) {
      len2--;
      g.changeAt(len2, u[i - len2], char(0));
    }
    if(len1 == len2 && g == ms) ans = min<int>(ans, i + 2);
    // dump(i, g, ms);
  }
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  cin >> n >> t;
  // n = t.size();
  auto c = cycle(t).back();
  ans = n;
  ans2 = n;
  check2(t);
  auto s = t.substr(0, c);
  if(c % 2) s = s + s, c = c + c;
  check(s);
  check(s + s);
  string f = t;
  int k = ans;
  // assert(k >= 1);
  // assert(k <= n);
  // if(k > 1) {
  //   for(int i = 0; i < n; i++) f.at(i) = t.at(k-1-abs(i % (2 * k - 2) - k + 1));
  //   // assert(f == t);
  //   if(f != t) {
  //     ans = ans2;
  //   }
  // }
  cout << ans << endl;
  return 0;
}
// 長さ1ダメなんですね！すみませんでした



Measured memory_bytes: 36356