#include <bits/stdc++.h>
#define ll long long
#define INF 1000000005
#define MOD 1000000007
#define EPS 1e-10
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define rrep(i,n) for(int i=(int)(n)-1;i>=0;--i)
#define srep(i,s,t) for(int i=(int)(s);i<(int)(t);++i)
#define each(a,b) for(auto& (a): (b))
#define all(v) (v).begin(),(v).end()
#define len(v) (int)(v).size()
#define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end())
#define cmx(x,y) x=max(x,y)
#define cmn(x,y) x=min(x,y)
#define fi first
#define se second
#define pb push_back
#define show(x) cout<<#x<<" = "<<(x)<<endl
#define sar(a,n) cout<<#a<<":";rep(pachico,n)cout<<" "<<a[pachico];cout<<endl

using namespace std;

template<typename S,typename T>auto&operator<<(ostream&o,pair<S,T>p){return o<<"{"<<p.fi<<","<<p.se<<"}";}
template<typename T>auto&operator<<(ostream&o,set<T>s){for(auto&e:s)o<<e<<" ";return o;}
template<typename S,typename T,typename U>
auto&operator<<(ostream&o,priority_queue<S,T,U>q){while(!q.empty())o<<q.top()<<" ",q.pop();return o;}
template<typename K,typename T>auto&operator<<(ostream&o,map<K,T>m){for(auto&e:m)o<<e<<" ";return o;}
template<typename T>auto&operator<<(ostream&o,vector<T>v){for(auto&e:v)o<<e<<" ";return o;}
void ashow(){cout<<endl;}template<typename T,typename...A>void ashow(T t,A...a){cout<<t<<" ";ashow(a...);}

typedef pair<int,int> P;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef vector<P> vp;
typedef vector<double> vd;
typedef vector<string> vs;

const int MAX_N = 100005;

int K = 0;

template<class _Key, class _Tp> class MapIterator;

template<class _Key, class _Tp> class Map {
private:
    using iterator = MapIterator<_Key, _Tp>;
    using data_type = pair<const _Key, _Tp>;
    struct node {
        data_type data;
        node *_M_left, *_M_right, *_M_parent;
        node(data_type&& _data) noexcept
            : data(move(_data)), _M_left(nullptr), _M_right(nullptr), _M_parent(nullptr){}
        inline const _Key& get_key() const noexcept { return data.first; }
        inline bool isRoot() const noexcept { return !_M_parent; }
        void rotate(const bool right){
            node *p = _M_parent, *g = p->_M_parent;
            if(right){
                if((p->_M_left = _M_right)) _M_right->_M_parent = p;
                _M_right = p, p->_M_parent = this;
            }else{
                if((p->_M_right = _M_left)) _M_left->_M_parent = p;
                _M_left = p, p->_M_parent = this;
            }
            if(!(_M_parent = g)) return;
            if(g->_M_left == p) g->_M_left = this;
            if(g->_M_right == p) g->_M_right = this;
        }
    };
    friend MapIterator<_Key, _Tp>;
public:
    node *root, *_M_header, *start;
    size_t _M_node_count;
    inline void confirm_header(){
        if(!_M_header){
            data_type new_data;
            root = _M_header = start = new node(move(new_data));
        }
    }
    node *splay(node *u){
        while(!(u->isRoot())){
            node *p = u->_M_parent, *gp = p->_M_parent;
            if(p->isRoot()){
                u->rotate((u == p->_M_left));
            }else{
                bool flag = (u == p->_M_left);
                if((u == p->_M_left) == (p == gp->_M_left)){
                    p->rotate(flag), u->rotate(flag);
                }else{
                    u->rotate(flag), u->rotate(!flag);
                }
            }
        }
        return root = u;
    }
    static node *increment(node *ver){
        if(ver->_M_right){
            ver = ver->_M_right;
            while(ver->_M_left) ver = ver->_M_left;
        }else{
            node *nx = ver->_M_parent;
            while(ver == nx->_M_right) ver = nx, nx = nx->_M_parent;
            ver = nx;
        }
        return ver;
    }
    node *join(node *ver1, node *ver2, const node *ver){
        while(ver2->_M_left) ver2 = ver2->_M_left;
        splay(ver2)->_M_left = ver1;
        return ver1 ? (ver1->_M_parent = ver2) : (start = ver2);
    }
    template<typename Key>
    node *_find(Key&& key, bool push = false){
        confirm_header();
        node *cur = nullptr, *nx = root;
        do {
            cur = nx;
            if(cur == _M_header || cur->get_key() > key) nx = cur->_M_left;
            else if(cur->get_key() < key) nx = cur->_M_right;
            else return splay(cur);
        }while(nx);
        if(!push) return _M_header;
        if(cur == _M_header || cur->get_key() > key){
            data_type new_data(forward<Key>(key), _Tp());
            nx = new node(move(new_data));
            cur->_M_left = nx, nx->_M_parent = cur;
            if(cur == start) start = nx;
            return _M_node_count++, splay(nx);
        }else{
            data_type new_data(forward<Key>(key), _Tp());
            nx = new node(move(new_data));
            cur->_M_right = nx, nx->_M_parent = cur;
            return _M_node_count++, splay(nx);
        }
    }
    template<typename Data>
    node *_insert(Data&& data){
        confirm_header();
        const _Key& key = data.first;
        node *cur = nullptr, *nx = root;
        do {
            cur = nx;
            if(cur == _M_header || cur->get_key() > key) nx = cur->_M_left;
            else if(cur->get_key() < key) nx = cur->_M_right;
            else return splay(cur);
        }while(nx);
        if(cur == _M_header || cur->get_key() > key){
            data_type new_data = forward<Data>(data);
            nx = new node(move(new_data));
            cur->_M_left = nx, nx->_M_parent = cur;
            if(cur == start) start = nx;
            return _M_node_count++, splay(nx);
        }else{
            data_type new_data = forward<Data>(data);
            nx = new node(move(new_data));
            cur->_M_right = nx, nx->_M_parent = cur;
            return _M_node_count++, splay(nx);
        }
    }
    node *_erase(node *root_ver){
        confirm_header();
        assert(root_ver != _M_header);
        if(root_ver->_M_left) root_ver->_M_left->_M_parent = nullptr;
        if(root_ver->_M_right) root_ver->_M_right->_M_parent = nullptr;
        node *res = join(root_ver->_M_left, root_ver->_M_right, root_ver);
        delete root_ver;
        return _M_node_count--, res;
    }
    node *_erase(const _Key& _key){
        node *ver = _find(_key);
        return _erase(ver);
    }
    node *_lower_bound(const _Key& _key){
        confirm_header();
        node *cur = nullptr, *nx = root, *res = nullptr;
        do {
            cur = nx;
            if(cur == _M_header){ nx = cur->_M_left; continue; }
            else if(cur->get_key() >= _key){
                nx = cur->_M_left;
                if(!res || cur->get_key() <= res->get_key()) res = cur;
            }else nx = cur->_M_right;
        }while(nx);
        splay(cur);
        return res ? res : _M_header;
    }
    node *_upper_bound(const _Key& _key){
        confirm_header();
        node *cur = nullptr, *nx = root, *res = nullptr;
        do {
            cur = nx;
            if(cur == _M_header){ nx = cur->_M_left; continue; }
            else if(cur->get_key() > _key){
                nx = cur->_M_left;
                if(!res || cur->get_key() <= res->get_key()) res = cur;
            }else nx = cur->_M_right;
        }while(nx);
        splay(cur);
        return res ? res : _M_header;
    }
    void clear_dfs(node *cur){
        if(cur->_M_left) clear_dfs(cur->_M_left);
        if(cur->_M_right) clear_dfs(cur->_M_right);
        delete cur;
    }

public:
    Map() noexcept : root(nullptr), _M_header(nullptr), start(nullptr), _M_node_count(0){}
    // ~Map() noexcept { if(root) clear_dfs(root); }
    friend ostream& operator<< (ostream& os, Map& mp) noexcept {
        for(auto& val : mp) os << '{' << val.first << ',' << val.second << "} ";
        return os;
    }
    _Tp& operator[](const _Key& _key){ return _find(_key, true)->data.second; }
    _Tp& operator[](_Key&& _key){
        node *res = _find(move(_key), true);
        return res->data.second;
    }
    const _Tp& at(const _Key& _key){
        node *res = _find(_key);
        if(res == _M_header) __throw_out_of_range(__N("Map::at"));
        return res->data.second;
    }
    size_t size() const noexcept { return _M_node_count; }
    bool empty() const noexcept { return size() == 0; }
    iterator begin() noexcept { return confirm_header(), iterator(start); }
    iterator end() noexcept { return confirm_header(), iterator(_M_header); }
    void clear() noexcept {
        clear_dfs(root), _M_node_count = 0;
        data_type new_data;
        root = _M_header = start = new node(move(new_data));
    }
    iterator find(const _Key& _key) noexcept { return iterator(_find(_key)); }
    iterator insert(const data_type& data) noexcept { return iterator(_insert(data)); }
    iterator insert(data_type&& data) noexcept { return iterator(_insert(move(data))); }
    iterator erase(const _Key& _key){ return iterator(_erase(_key)); }
    iterator erase(const iterator& itr){ return iterator(_erase(splay(itr.node_ptr))); }
    iterator lower_bound(const _Key& _key) noexcept { return iterator(_lower_bound(_key)); }
    iterator upper_bound(const _Key& _key) noexcept { return iterator(_upper_bound(_key)); }
};

template<class _Key, class _Tp>
class MapIterator {
private:
    friend Map<_Key, _Tp>;
    typename Map<_Key, _Tp>::node *node_ptr;
    using iterator_category = forward_iterator_tag;
    using value_type = pair<const _Key, _Tp>;
    using difference_type = pair<const _Key, _Tp>;
    using pointer = pair<const _Key, _Tp>*;
    using reference = pair<const _Key, _Tp>&;

private:
    MapIterator(typename Map<_Key, _Tp>::node *mp) noexcept : node_ptr(mp){}

public:
    MapIterator() noexcept : node_ptr(){}
    MapIterator(const MapIterator& itr) noexcept : node_ptr(itr.node_ptr){}
    MapIterator& operator=(const MapIterator& itr) & noexcept { return node_ptr = itr.node_ptr, *this; }
    MapIterator& operator=(const MapIterator&& itr) & noexcept { return node_ptr = itr.node_ptr, *this; }
    reference operator*() const { return node_ptr->data; }
    pointer operator->() const { return &(node_ptr->data); }
    MapIterator& operator++() noexcept { return node_ptr = Map<_Key, _Tp>::increment(node_ptr), *this; }
    MapIterator operator++(int) const noexcept { return MapIterator(Map<_Key, _Tp>::increment(this->node_ptr)); }
    bool operator==(const MapIterator& itr) const noexcept { return !(*this != itr); };
    bool operator!=(const MapIterator& itr) const noexcept { return node_ptr != itr.node_ptr; }
};

struct SW {
    chrono::high_resolution_clock::time_point st,ed;
    void start() {
        st = chrono::high_resolution_clock::now();
    }
    void end() {
        ed = chrono::high_resolution_clock::now();
        cout << chrono::duration_cast<chrono::milliseconds>(ed - st).count() << " msec\n";
    }
};


Map<string,Map<string,int> > mp[2];

int main()
{
    SW sw;
    sw.start();
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    n *= 2;
    string s;
    cin >> s;
    rep(i,(1 << (n-n/2))){
        string red,blue;
        rep(j,n-n/2){
            if((i >> j) & 1){
                red.pb(s[j+n/2]);
            }else{
                blue.pb(s[j+n/2]);
            }
        }
        reverse(all(blue));
        if(len(red) <= len(blue)){
            mp[0][move(blue)][move(red)]++;
        }else{
            mp[1][move(red)][move(blue)]++;
        }
        ++K;
    }
    ll ans = 0;
    rep(i,(1 << n/2)){
        string red, blue;
        rep(j,n/2){
            if((i >> j) & 1){
                red.pb(s[j]);
            }else{
                blue.pb(s[j]);
            }
        }
        reverse(all(blue));
        if(len(red) >= len(blue)){
            ans += mp[0][move(red)][move(blue)];
        }else{
            ans += mp[1][move(blue)][move(red)];
        }
    }
    cout << ans << "\n";
    // sw.end();
    return 0;
}


Measured memory_bytes: 131328