#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define forab(i, a, b) for (int i = int(a); i < int(b); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define fst first
#define snd second

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pii = pair<int, int>;
using vvi = vector<vi>;
using vii = vector<pii>;

#ifdef LOCAL
#define eprintf(args...) fprintf(stderr, args), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define FILE_NAME "a"

string s;

bool read() {
    if (!(cin >> s)) {
        return 0;
    }
    return 1;
}

const int mod = (int)1e9 + 7;

void add (int &a, int b)
{
    a += b;
    if (a >= mod)
        a -= mod;
}

void sub (int &a, int b)
{
    a -= b;
    if (a < 0)
        a += mod;
}

void kill (vi &v)
{
    v.clear();
    v.shrink_to_fit();
}

struct gap_jumper
{
    string s;
    vi value;
    int n;

    gap_jumper (string s_, int n_)
    {
        n = n_;
        value.resize(n + 1);
        s = s_;
        assert(sz(s) == 2 * n);
    }

    vi d_was;
    vvi next_, prev_, sum_;

    int get_id (int step)
    {

        int pos = find(all(d_was), step) - d_was.begin();
        if (pos != sz(d_was))
            return pos;

        d_was.pb(step);
        next_.pb(vi(2 * n)), prev_.pb(vi(2 * n)), sum_.pb(vi());
        sum_.back().reserve(n);

        vi &next = next_.back();
        vi &prev = prev_.back();

        ford (i, 2 * n)
        {
            if (i + step >= 2 * n)
                next[i] = 1;
            else
                next[i] = (s[i] != s[i + step] ? 1 : next[i + step] + 1);
        }

        forn (i, 2 * n)
        {
            if (i < step)
                prev[i] = 1;
            else
                prev[i] = (s[i] != s[i - step] ? 1 : prev[i - step] + 1);
        }

        return pos;
    }

    int first_left (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &prev = prev_[id];

        if (what != s[pos])
            return 0;
        return prev[pos];
    }

    int first_right (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &next = next_[id];

        if (what != s[pos])
            return 0;
        return next[pos];
    }

    int sum (int pos, int step, int len)
    {
        const int id = get_id(step);
        vi &sum = sum_[id];

        int to = pos + step * (len - 1);
        assert(0 <= pos && pos <= to && to < sz(value));

        while (sz(sum) <= to)
        {
            const int cur_id = sz(sum);
            sum.pb(value[cur_id]);
            if (cur_id >= step)
                add(sum.back(), sum[cur_id - step]);
        }

        int res = sum[to];
        if (pos - step >= 0)
            sub(res, sum[pos - step]);

        return res;
    }

    void purge (const vi &allowed)
    {
        vi to_del;
        forn (i, sz(d_was))
        {
            const int id = d_was[i];
            if (!binary_search(all(allowed), id))
                to_del.pb(i);
        }

        reverse(all(to_del));
        for (int id : to_del)
        {
            d_was[id] = -1;
            kill(sum_[id]);
            kill(prev_[id]);
            kill(next_[id]);
        }
    }
};

struct prog
{
    int start, diff, len;

    int get (int id) const
    {
        return start + diff * id;
    }

    int get_end () const
    {
        return start + diff * (len - 1);
    }
};

// poor man OOP starting :)
void relax (vector<prog> &v)
{
        vector<prog> nv;

            for (const auto &pr : v)
                    {
                                if (pr.len == 0)
                                                continue;

                                        if (nv.empty())
                                                        nv.pb(pr);
                                                else
                                                            {
                                                                            auto &top = nv.back();
                                                                                if (top.len == 1 && pr.len == 1)
                                                                                top = prog{top.start, pr.start - top.start, 2};
                                                                                else if (top.len == 1 && pr.start - top.start == pr.diff)
                                                                                {
                                                                                top = prog{top.start, pr.diff, pr.len + 1};
                                                                                }
                                                                                else if (pr.len == 1 && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len++;
                                                                                }
                                                                                else if (pr.diff == top.diff && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len += pr.len;
                                                                                }
                                                                                else
                                                                                {
                                                                                nv.pb(pr);
                                                                                }
                                                                                }
                                                    }

                v.swap(nv);
}

void incr_all (vector<prog> &v, int delta)
{
    for (auto &pr : v)
        pr.start += delta;
}

void add_start (vector<prog> &v, int num)
{
    assert(v.empty() || num < v.front().start);
    v.insert(v.begin(), prog{num, 1, 1});
}

void del (vector<prog> &v, const vi &who)
{
    int ptr = 0;
    vector<prog> nv;

    for (const auto &pr : v)
    {
        int last_alive = 0;
        while (ptr < sz(who) && pr.start <= who[ptr] && who[ptr] <= pr.get_end())
        {
            assert((who[ptr] - pr.start) % pr.diff == 0);
            int cur_id = (who[ptr] - pr.start) / pr.diff;
            if (last_alive < cur_id)
                nv.pb(prog{pr.get(last_alive), pr.diff, cur_id - last_alive});

            assert(last_alive <= cur_id);
            last_alive = cur_id + 1;
            ptr++;
        }

        const int total = pr.len;
        if (last_alive < total)
            nv.pb(prog{pr.get(last_alive), pr.diff, total - last_alive});
    }

    v.swap(nv);
    relax(v);
}

void print (const vector<prog> &v)
{
    for (const auto &pr : v)
    {
        forn (i, pr.len)
            eprintf("%d ", pr.get(i));
    }
    eprintf("\n");
}

double time ()
{
    return (double)clock() / CLOCKS_PER_SEC;
}

int work_old() {
        const int n = sz(s) / 2;
            assert(sz(s) == 2 * n);

                vi dp(n + 1);
                    dp[0] = 1;

                        vi pref;

                            forn (len, n + 1) if (len)
                                    {
                                            if (sz(pref) >= 50)
                                                return -1;

                                                const int l = n - len, r = n + len;

                                                        vi npref;
                                                                for (int i : pref)
                                                                            {
                                                                                if (s[l] == s[r - i - 2] && s[l + i + 1] == s[r - 1] && i + 2 <= len)
                                                                                npref.pb(i + 2);
                                                                                }

                                                                        if (s[l] == s[r - 1])
                                                                                npref.pb(1);
                                                                                if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
                                                                                npref.pb(2);

                                                                                pref = npref;
                                                                                /*
                                                                                *         eprintf("for len = %d\n", len);
                                                                                *                 for (int x : pref)
                                                                                *                             eprintf("%d ", x);
                                                                                *                                     eprintf("\n");
                                                                                *                                     */
                                                                                for (int i : pref)
                                                                                add(dp[len], dp[len - i]);
                                                                                }

                                return dp[n];
}

void solve() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    int ans = work_old ();
    if (ans != -1)
    {
        cout << ans << endl;
        return;
    }

    gap_jumper info(s, n);

    vi dp(n + 1);
    dp[0] = 1;
    info.value[0] = 1;

    vector<prog> pref;

    forn (len, n + 1) if (len)
    {
        const int l = n - len, r = n + len;

        vi to_del;

        for (const auto &pr : pref)
        {
            for (int i = 0; i < pr.len; )
            {
                int cur = pr.get(i);
                const int left_steps = info.first_left(r - cur - 2, pr.diff, s[l]);
                const int right_steps = info.first_right(l + cur + 1, pr.diff, s[r - 1]);
                const int steps = min(left_steps, right_steps);

                i += steps;
                if (i >= pr.len)
                    break;

                cur = pr.get(i);
                assert(!(s[l] == s[r - cur - 2] && s[l + cur + 1] == s[r - 1]));
                to_del.pb(cur);
                i++;
            }
        }

        if (!pref.empty() && pref.back().get_end() == len - 1 && !count(all(to_del), len - 1))
            to_del.pb(len - 1);

        del(pref, to_del);

        incr_all(pref, 2);

        if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
            add_start(pref, 2);
        if (s[l] == s[r - 1])
            add_start(pref, 1);

        relax(pref);
        assert(sz(pref) <= 20);

//        eprintf("for len = %d:\n", len);
//        print(pref);

        for (const auto &pr : pref)
        {
            int start = len - pr.get_end();
            int cur_sum = info.sum(start, pr.diff, pr.len);
            add(dp[len], cur_sum);
        }

        vi allowed;
        for (const auto &pr : pref)
            allowed.pb(pr.diff);
        sort(all(allowed));
        allowed.resize(unique(all(allowed)) - allowed.begin());

        info.value[len] = dp[len];
    }

    cout << dp[n] << endl;
}

int main() {
#ifdef LOCAL
    freopen(FILE_NAME ".in", "r", stdin);
//    freopen(FILE_NAME ".out", "w", stdout);
#endif

    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (read()) {
        solve();
//        break;
    }

    return 0;
}


#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define forab(i, a, b) for (int i = int(a); i < int(b); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define fst first
#define snd second

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pii = pair<int, int>;
using vvi = vector<vi>;
using vii = vector<pii>;

#ifdef LOCAL
#define eprintf(args...) fprintf(stderr, args), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define FILE_NAME "a"

string s;

bool read() {
    if (!(cin >> s)) {
        return 0;
    }
    return 1;
}

const int mod = (int)1e9 + 7;

void add (int &a, int b)
{
    a += b;
    if (a >= mod)
        a -= mod;
}

void sub (int &a, int b)
{
    a -= b;
    if (a < 0)
        a += mod;
}

void solve() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    vi dp(n + 1);
    dp[0] = 1;

    vi pref;

    forn (len, n + 1) if (len)
    {
        const int l = n - len, r = n + len;

        vi npref;
        for (int i : pref)
        {
            if (s[l] == s[r - i - 2] && s[l + i + 1] == s[r - 1] && i + 2 <= len)
                npref.pb(i + 2);
        }

        if (s[l] == s[r - 1])
            npref.pb(1);
        if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
            npref.pb(2);

        pref = npref;

        for (int i : pref)
            add(dp[len], dp[len - i]);
    }

    cout << dp[n] << endl;
}

int main() {
#ifdef LOCAL
    freopen(FILE_NAME ".in", "r", stdin);
//    freopen(FILE_NAME ".out", "w", stdout);
#endif

    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (read()) {
        solve();
    }

    return 0;
}


#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define forab(i, a, b) for (int i = int(a); i < int(b); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define fst first
#define snd second

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pii = pair<int, int>;
using vvi = vector<vi>;
using vii = vector<pii>;

#ifdef LOCAL
#define eprintf(args...) fprintf(stderr, args), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define FILE_NAME "a"

string s;

bool read() {
    if (!(cin >> s)) {
        return 0;
    }
    return 1;
}

const int mod = (int)1e9 + 7;

void add (int &a, int b)
{
    a += b;
    if (a >= mod)
        a -= mod;
}

void sub (int &a, int b)
{
    a -= b;
    if (a < 0)
        a += mod;
}

struct gap_jumper
{
    string s;
    vi value;
    int n;

    gap_jumper (string s_, int n_)
    {
        n = n_;
        value.resize(n + 1);
        s = s_;
        assert(sz(s) == 2 * n);
    }

    vi d_was;
    vvi next_, prev_, sum_;

    int get_id (int step)
    {

        int pos = find(all(d_was), step) - d_was.begin();
        if (pos != sz(d_was))
            return pos;

        d_was.pb(step);
        next_.pb(vi(2 * n)), prev_.pb(vi(2 * n)), sum_.pb(vi());
        sum_.back().reserve(n);

        vi &next = next_.back();
        vi &prev = prev_.back();

        ford (i, 2 * n)
        {
            if (i + step >= 2 * n)
                next[i] = 1;
            else
                next[i] = (s[i] != s[i + step] ? 1 : next[i + step] + 1);
        }

        forn (i, 2 * n)
        {
            if (i < step)
                prev[i] = 1;
            else
                prev[i] = (s[i] != s[i - step] ? 1 : prev[i - step] + 1);
        }

        return pos;
    }

    int first_left (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &prev = prev_[id];

        if (what != s[pos])
            return 0;
        return prev[pos];
    }

    int first_right (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &next = next_[id];

        if (what != s[pos])
            return 0;
        return next[pos];
    }

    int sum (int pos, int step, int len)
    {
        const int id = get_id(step);
        vi &sum = sum_[id];

        int to = pos + step * (len - 1);
        assert(0 <= pos && pos <= to && to < sz(value));

        while (sz(sum) <= to)
        {
            const int cur_id = sz(sum);
            sum.pb(value[cur_id]);
            if (cur_id >= step)
                add(sum.back(), sum[cur_id - step]);
        }

        int res = sum[to];
        if (pos - step >= 0)
            sub(res, sum[pos - step]);

        return res;
    }
};

struct prog
{
    int start, diff, len;

    int get (int id) const
    {
        return start + diff * id;
    }

    int get_end () const
    {
        return start + diff * (len - 1);
    }
};

// poor man OOP starting :)
void relax (vector<prog> &v)
{
        vector<prog> nv;

            for (const auto &pr : v)
                    {
                                if (pr.len == 0)
                                                continue;

                                        if (nv.empty())
                                                        nv.pb(pr);
                                                else
                                                            {
                                                                            auto &top = nv.back();
                                                                                if (top.len == 1 && pr.len == 1)
                                                                                top = prog{top.start, pr.start - top.start, 2};
                                                                                else if (top.len == 1 && pr.start - top.start == pr.diff)
                                                                                {
                                                                                top = prog{top.start, pr.diff, pr.len + 1};
                                                                                }
                                                                                else if (pr.len == 1 && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len++;
                                                                                }
                                                                                else if (pr.diff == top.diff && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len += pr.len;
                                                                                }
                                                                                else
                                                                                {
                                                                                nv.pb(pr);
                                                                                }
                                                                                }
                                                    }

                v.swap(nv);
}

void incr_all (vector<prog> &v, int delta)
{
    for (auto &pr : v)
        pr.start += delta;
}

void add_start (vector<prog> &v, int num)
{
    assert(v.empty() || num < v.front().start);
    v.insert(v.begin(), prog{num, 1, 1});
}

void del (vector<prog> &v, const vi &who)
{
    int ptr = 0;
    vector<prog> nv;

    for (const auto &pr : v)
    {
        int last_alive = 0;
        while (ptr < sz(who) && pr.start <= who[ptr] && who[ptr] <= pr.get_end())
        {
            assert((who[ptr] - pr.start) % pr.diff == 0);
            int cur_id = (who[ptr] - pr.start) / pr.diff;
            if (last_alive < cur_id)
                nv.pb(prog{pr.get(last_alive), pr.diff, cur_id - last_alive});

            assert(last_alive <= cur_id);
            last_alive = cur_id + 1;
            ptr++;
        }

        const int total = pr.len;
        if (last_alive < total)
            nv.pb(prog{pr.get(last_alive), pr.diff, total - last_alive});
    }

    v.swap(nv);
    relax(v);
}

void print (const vector<prog> &v)
{
    for (const auto &pr : v)
    {
        forn (i, pr.len)
            eprintf("%d ", pr.get(i));
    }
    eprintf("\n");
}

void solve() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    gap_jumper info(s, n);

    vi dp(n + 1);
    dp[0] = 1;
    info.value[0] = 1;

    vector<prog> pref;

    forn (len, n + 1) if (len)
    {
        const int l = n - len, r = n + len;

        vi to_del;

        for (const auto &pr : pref)
        {
            for (int i = 0; i < pr.len; )
            {
                int cur = pr.get(i);
                const int left_steps = info.first_left(r - cur - 2, pr.diff, s[l]);
                const int right_steps = info.first_right(l + cur + 1, pr.diff, s[r - 1]);
                const int steps = min(left_steps, right_steps);

                i += steps;
                if (i >= pr.len)
                    break;

                cur = pr.get(i);
                assert(!(s[l] == s[r - cur - 2] && s[l + cur + 1] == s[r - 1]));
                to_del.pb(cur);
                i++;
            }
        }

        if (!pref.empty() && pref.back().get_end() == len - 1 && !count(all(to_del), len - 1))
            to_del.pb(len - 1);

        del(pref, to_del);

        incr_all(pref, 2);

        if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
            add_start(pref, 2);
        if (s[l] == s[r - 1])
            add_start(pref, 1);

        relax(pref);
        assert(sz(pref) <= 20);

//        eprintf("for len = %d:\n", len);
//        print(pref);

        for (const auto &pr : pref)
        {
            int start = len - pr.get_end();
            int cur_sum = info.sum(start, pr.diff, pr.len);
            add(dp[len], cur_sum);
        }

        info.value[len] = dp[len];
    }

    cout << dp[n] << endl;
}

int main() {
#ifdef LOCAL
    freopen(FILE_NAME ".in", "r", stdin);
//    freopen(FILE_NAME ".out", "w", stdout);
#endif

    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (read()) {
        solve();
//        break;
    }

    return 0;
}


#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define forab(i, a, b) for (int i = int(a); i < int(b); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define fst first
#define snd second

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pii = pair<int, int>;
using vvi = vector<vi>;
using vii = vector<pii>;

#ifdef LOCAL
#define eprintf(args...) fprintf(stderr, args), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define FILE_NAME "a"

string s;

bool read() {
    if (!(cin >> s)) {
        return 0;
    }
    return 1;
}

const int mod = (int)1e9 + 7;

void add (int &a, int b)
{
    a += b;
    if (a >= mod)
        a -= mod;
}

void sub (int &a, int b)
{
    a -= b;
    if (a < 0)
        a += mod;
}

void kill (vi &v)
{
    v.clear();
    v.shrink_to_fit();
}

struct gap_jumper
{
    string s;
    vi value;
    int n;

    gap_jumper (string s_, int n_)
    {
        n = n_;
        value.resize(n + 1);
        s = s_;
        assert(sz(s) == 2 * n);
    }

    vi d_was;
    vvi next_, prev_, sum_;

    int get_id (int step)
    {

        int pos = find(all(d_was), step) - d_was.begin();
        if (pos != sz(d_was))
            return pos;

        d_was.pb(step);
        next_.pb(vi(2 * n)), prev_.pb(vi(2 * n)), sum_.pb(vi());
        sum_.back().reserve(n);

        vi &next = next_.back();
        vi &prev = prev_.back();

        ford (i, 2 * n)
        {
            if (i + step >= 2 * n)
                next[i] = 1;
            else
                next[i] = (s[i] != s[i + step] ? 1 : next[i + step] + 1);
        }

        forn (i, 2 * n)
        {
            if (i < step)
                prev[i] = 1;
            else
                prev[i] = (s[i] != s[i - step] ? 1 : prev[i - step] + 1);
        }

        return pos;
    }

    int first_left (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &prev = prev_[id];

        if (what != s[pos])
            return 0;
        return prev[pos];
    }

    int first_right (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &next = next_[id];

        if (what != s[pos])
            return 0;
        return next[pos];
    }

    int sum (int pos, int step, int len)
    {
        const int id = get_id(step);
        vi &sum = sum_[id];

        int to = pos + step * (len - 1);
        assert(0 <= pos && pos <= to && to < sz(value));

        while (sz(sum) <= to)
        {
            const int cur_id = sz(sum);
            sum.pb(value[cur_id]);
            if (cur_id >= step)
                add(sum.back(), sum[cur_id - step]);
        }

        int res = sum[to];
        if (pos - step >= 0)
            sub(res, sum[pos - step]);

        return res;
    }

    void purge (const vi &allowed)
    {
        vi to_del;
        forn (i, sz(d_was))
        {
            const int id = d_was[i];
            if (!binary_search(all(allowed), id))
                to_del.pb(i);
        }

        reverse(all(to_del));
        for (int id : to_del)
        {
            d_was[id] = -1;
            kill(sum_[id]);
            kill(prev_[id]);
            kill(next_[id]);
        }
    }
};

struct prog
{
    int start, diff, len;

    int get (int id) const
    {
        return start + diff * id;
    }

    int get_end () const
    {
        return start + diff * (len - 1);
    }
};

// poor man OOP starting :)
void relax (vector<prog> &v)
{
        vector<prog> nv;

            for (const auto &pr : v)
                    {
                                if (pr.len == 0)
                                                continue;

                                        if (nv.empty())
                                                        nv.pb(pr);
                                                else
                                                            {
                                                                            auto &top = nv.back();
                                                                                if (top.len == 1 && pr.len == 1)
                                                                                top = prog{top.start, pr.start - top.start, 2};
                                                                                else if (top.len == 1 && pr.start - top.start == pr.diff)
                                                                                {
                                                                                top = prog{top.start, pr.diff, pr.len + 1};
                                                                                }
                                                                                else if (pr.len == 1 && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len++;
                                                                                }
                                                                                else if (pr.diff == top.diff && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len += pr.len;
                                                                                }
                                                                                else
                                                                                {
                                                                                nv.pb(pr);
                                                                                }
                                                                                }
                                                    }

                v.swap(nv);
}

void incr_all (vector<prog> &v, int delta)
{
    for (auto &pr : v)
        pr.start += delta;
}

void add_start (vector<prog> &v, int num)
{
    assert(v.empty() || num < v.front().start);
    v.insert(v.begin(), prog{num, 1, 1});
}

void del (vector<prog> &v, const vi &who)
{
    int ptr = 0;
    vector<prog> nv;

    for (const auto &pr : v)
    {
        int last_alive = 0;
        while (ptr < sz(who) && pr.start <= who[ptr] && who[ptr] <= pr.get_end())
        {
            assert((who[ptr] - pr.start) % pr.diff == 0);
            int cur_id = (who[ptr] - pr.start) / pr.diff;
            if (last_alive < cur_id)
                nv.pb(prog{pr.get(last_alive), pr.diff, cur_id - last_alive});

            assert(last_alive <= cur_id);
            last_alive = cur_id + 1;
            ptr++;
        }

        const int total = pr.len;
        if (last_alive < total)
            nv.pb(prog{pr.get(last_alive), pr.diff, total - last_alive});
    }

    v.swap(nv);
    relax(v);
}

void print (const vector<prog> &v)
{
    for (const auto &pr : v)
    {
        forn (i, pr.len)
            eprintf("%d ", pr.get(i));
    }
    eprintf("\n");
}

void solve() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    gap_jumper info(s, n);

    vi dp(n + 1);
    dp[0] = 1;
    info.value[0] = 1;

    vector<prog> pref;

    forn (len, n + 1) if (len)
    {
        const int l = n - len, r = n + len;

        vi to_del;

        for (const auto &pr : pref)
        {
            for (int i = 0; i < pr.len; )
            {
                int cur = pr.get(i);
                const int left_steps = info.first_left(r - cur - 2, pr.diff, s[l]);
                const int right_steps = info.first_right(l + cur + 1, pr.diff, s[r - 1]);
                const int steps = min(left_steps, right_steps);

                i += steps;
                if (i >= pr.len)
                    break;

                cur = pr.get(i);
                assert(!(s[l] == s[r - cur - 2] && s[l + cur + 1] == s[r - 1]));
                to_del.pb(cur);
                i++;
            }
        }

        if (!pref.empty() && pref.back().get_end() == len - 1 && !count(all(to_del), len - 1))
            to_del.pb(len - 1);

        del(pref, to_del);

        incr_all(pref, 2);

        if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
            add_start(pref, 2);
        if (s[l] == s[r - 1])
            add_start(pref, 1);

        relax(pref);
        assert(sz(pref) <= 20);

//        eprintf("for len = %d:\n", len);
//        print(pref);

        for (const auto &pr : pref)
        {
            int start = len - pr.get_end();
            int cur_sum = info.sum(start, pr.diff, pr.len);
            add(dp[len], cur_sum);
        }

        vi allowed;
        for (const auto &pr : pref)
            allowed.pb(pr.diff);
        sort(all(allowed));
        allowed.resize(unique(all(allowed)) - allowed.begin());

        if (false)
            info.purge(allowed);
        info.value[len] = dp[len];
    }

    cout << dp[n] << endl;
}

int main() {
#ifdef LOCAL
    freopen(FILE_NAME ".in", "r", stdin);
//    freopen(FILE_NAME ".out", "w", stdout);
#endif

    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (read()) {
        solve();
//        break;
    }

    return 0;
}


#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define forab(i, a, b) for (int i = int(a); i < int(b); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define fst first
#define snd second

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pii = pair<int, int>;
using vvi = vector<vi>;
using vii = vector<pii>;

#ifdef LOCAL
#define eprintf(args...) fprintf(stderr, args), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define FILE_NAME "a"

string s;

bool read() {
    if (!(cin >> s)) {
        return 0;
    }
    return 1;
}

const int mod = (int) 1e9 + 7;

void add(int &a, int b) {
    a += b;
    if (a >= mod)
        a -= mod;
}

void sub(int &a, int b) {
    a -= b;
    if (a < 0)
        a += mod;
}

void kill(vi &v) {
    v.clear();
    v.shrink_to_fit();
}

struct gap_jumper {
    string s;
    vi value;
    int n;

    gap_jumper(string s_, int n_) {
        n = n_;
        value.resize(n + 1);
        s = s_;
        assert(sz(s) == 2 * n);
    }

    vi d_was;
    vvi next_, prev_, sum_;

    int get_id(int step) {
        int pos = find(all(d_was), step) - d_was.begin();
        if (pos != sz(d_was))
            return pos;

        d_was.pb(step);
        next_.pb(vi(2 * n)), prev_.pb(vi(2 * n)), sum_.pb(vi());
        sum_.back().reserve(n);

        vi &next = next_.back();
        vi &prev = prev_.back();

        ford (i, 2 * n) {
            if (i + step >= 2 * n)
                next[i] = 1;
            else
                next[i] = (s[i] != s[i + step] ? 1 : next[i + step] + 1);
        }

        forn (i, 2 * n) {
            if (i < step)
                prev[i] = 1;
            else
                prev[i] = (s[i] != s[i - step] ? 1 : prev[i - step] + 1);
        }

        return pos;
    }

    int first_left(int pos, int step, char what) {
        const int id = get_id(step);
        const vi &prev = prev_[id];

        if (what != s[pos])
            return 0;
        return prev[pos];
    }

    int first_right(int pos, int step, char what) {
        const int id = get_id(step);
        const vi &next = next_[id];

        if (what != s[pos])
            return 0;
        return next[pos];
    }

    int sum(int pos, int step, int len) {
        const int id = get_id(step);
        vi &sum = sum_[id];

        int to = pos + step * (len - 1);
        assert(0 <= pos && pos <= to && to < sz(value));

        while (sz(sum) <= to) {
            const int cur_id = sz(sum);
            sum.pb(value[cur_id]);
            if (cur_id >= step)
                add(sum.back(), sum[cur_id - step]);
        }

        int res = sum[to];
        if (pos - step >= 0)
            sub(res, sum[pos - step]);

        return res;
    }
};

struct prog {
    int start, diff, len;

    int get(int id) const {
        return start + diff * id;
    }

    int get_end() const {
        return start + diff * (len - 1);
    }
};

// poor man OOP starting :)
void relax(vector<prog> &v) {
    vector<prog> nv;

    for (const auto &pr : v) {
        if (pr.len == 0)
            continue;

        if (nv.empty())
            nv.pb(pr);
        else {
            auto &top = nv.back();
            if (top.len == 1 && pr.len == 1)
                top = prog{top.start, pr.start - top.start, 2};
            else if (top.len == 1 && pr.start - top.start == pr.diff) {
                top = prog{top.start, pr.diff, pr.len + 1};
            } else if (pr.len == 1 && pr.start - top.get_end() == top.diff) {
                top.len++;
            } else if (pr.diff == top.diff && pr.start - top.get_end() == top.diff) {
                top.len += pr.len;
            } else {
                nv.pb(pr);
            }
        }
    }

    v.swap(nv);
}

void incr_all(vector<prog> &v, int delta) {
    for (auto &pr : v)
        pr.start += delta;
}

void add_start(vector<prog> &v, int num) {
    assert(v.empty() || num < v.front().start);
    v.insert(v.begin(), prog{num, 1, 1});
}

void del(vector<prog> &v, const vi &who) {
    int ptr = 0;
    vector<prog> nv;

    for (const auto &pr : v) {
        int last_alive = 0;
        while (ptr < sz(who) && pr.start <= who[ptr] && who[ptr] <= pr.get_end()) {
            assert((who[ptr] - pr.start) % pr.diff == 0);
            int cur_id = (who[ptr] - pr.start) / pr.diff;
            if (last_alive < cur_id)
                nv.pb(prog{pr.get(last_alive), pr.diff, cur_id - last_alive});

            assert(last_alive <= cur_id);
            last_alive = cur_id + 1;
            ptr++;
        }

        const int total = pr.len;
        if (last_alive < total)
            nv.pb(prog{pr.get(last_alive), pr.diff, total - last_alive});
    }

    v.swap(nv);
    relax(v);
}

void print(const vector<prog> &v) {
    for (const auto &pr : v) {
        forn (i, pr.len) eprintf("%d ", pr.get(i));
    }
    eprintf("\n");
}

double time() {
    return (double) clock() / CLOCKS_PER_SEC;
}

int work_old() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    vi dp(n + 1);
    dp[0] = 1;

    vi pref;

    forn (len, n + 1) if (len) {
            if (sz(pref) >= 50)
                return -1;

            const int l = n - len, r = n + len;

            vi npref;
            for (int i : pref) {
                if (s[l] == s[r - i - 2] && s[l + i + 1] == s[r - 1] && i + 2 <= len)
                    npref.pb(i + 2);
            }

            if (s[l] == s[r - 1])
                npref.pb(1);
            if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
                npref.pb(2);

            pref = npref;

            for (int i : pref)
                add(dp[len], dp[len - i]);
        }

    return dp[n];
}

void solve() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    gap_jumper info(s, n);

    vi dp(n + 1);
    dp[0] = 1;
    info.value[0] = 1;

    vector<prog> pref;

    forn (len, n + 1) if (len) {
            const int l = n - len, r = n + len;
            vi to_del;

            for (const auto &pr : pref) {
                for (int i = 0; i < pr.len;) {
                    int cur = pr.get(i);
                    const int left_steps = info.first_left(r - cur - 2, pr.diff, s[l]);
                    const int right_steps = info.first_right(l + cur + 1, pr.diff, s[r - 1]);
                    const int steps = min(left_steps, right_steps);

                    i += steps;
                    if (i >= pr.len)
                        break;

                    cur = pr.get(i);
                    assert(!(s[l] == s[r - cur - 2] && s[l + cur + 1] == s[r - 1]));
                    to_del.pb(cur);
                    i++;
                }
            }

            if (!pref.empty() && pref.back().get_end() == len - 1 && !count(all(to_del), len - 1))
                to_del.pb(len - 1);

            del(pref, to_del);

            incr_all(pref, 2);

            if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
                add_start(pref, 2);
            if (s[l] == s[r - 1])
                add_start(pref, 1);

            relax(pref);
            assert(sz(pref) <= 20);

            for (const auto &pr : pref) {
                int start = len - pr.get_end();
                int cur_sum = info.sum(start, pr.diff, pr.len);
                add(dp[len], cur_sum);
            }

            vi allowed;
            for (const auto &pr : pref)
                allowed.pb(pr.diff);
            sort(all(allowed));
            allowed.resize(unique(all(allowed)) - allowed.begin());

            info.value[len] = dp[len];
        }

    cout << dp[n] << endl;
}

int main() {
#ifdef LOCAL
//    freopen(FILE_NAME ".in", "r", stdin);
//    freopen(FILE_NAME ".out", "w", stdout);
#endif

    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (read()) {
        solve();
//        break;
    }

    return 0;
}


#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define forab(i, a, b) for (int i = int(a); i < int(b); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define fst first
#define snd second

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pii = pair<int, int>;
using vvi = vector<vi>;
using vii = vector<pii>;

#ifdef LOCAL
#define eprintf(args...) fprintf(stderr, args), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define FILE_NAME "a"

string s;

bool read() {
    if (!(cin >> s)) {
        return 0;
    }
    return 1;
}

const int mod = (int)1e9 + 7;

void add (int &a, int b)
{
    a += b;
    if (a >= mod)
        a -= mod;
}

void sub (int &a, int b)
{
    a -= b;
    if (a < 0)
        a += mod;
}

void kill (vi &v)
{
    v.clear();
    v.shrink_to_fit();
}

struct gap_jumper
{
    string s;
    vi value;
    int n;

    gap_jumper (string s_, int n_)
    {
        n = n_;
        value.resize(n + 1);
        s = s_;
        assert(sz(s) == 2 * n);
    }

    vi d_was;
    vvi next_, prev_, sum_;

    int get_id (int step)
    {

        int pos = find(all(d_was), step) - d_was.begin();
        if (pos != sz(d_was))
            return pos;

        d_was.pb(step);
        next_.pb(vi(2 * n)), prev_.pb(vi(2 * n)), sum_.pb(vi());
        sum_.back().reserve(n);

        vi &next = next_.back();
        vi &prev = prev_.back();

        ford (i, 2 * n)
        {
            if (i + step >= 2 * n)
                next[i] = 1;
            else
                next[i] = (s[i] != s[i + step] ? 1 : next[i + step] + 1);
        }

        forn (i, 2 * n)
        {
            if (i < step)
                prev[i] = 1;
            else
                prev[i] = (s[i] != s[i - step] ? 1 : prev[i - step] + 1);
        }

        return pos;
    }

    int first_left (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &prev = prev_[id];

        if (what != s[pos])
            return 0;
        return prev[pos];
    }

    int first_right (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &next = next_[id];

        if (what != s[pos])
            return 0;
        return next[pos];
    }

    int sum (int pos, int step, int len)
    {
        const int id = get_id(step);
        vi &sum = sum_[id];

        int to = pos + step * (len - 1);
        assert(0 <= pos && pos <= to && to < sz(value));

        while (sz(sum) <= to)
        {
            const int cur_id = sz(sum);
            sum.pb(value[cur_id]);
            if (cur_id >= step)
                add(sum.back(), sum[cur_id - step]);
        }

        int res = sum[to];
        if (pos - step >= 0)
            sub(res, sum[pos - step]);

        return res;
    }

    void purge (const vi &allowed)
    {
        vi to_del;
        forn (i, sz(d_was))
        {
            const int id = d_was[i];
            if (!binary_search(all(allowed), id))
                to_del.pb(i);
        }

        reverse(all(to_del));
        for (int id : to_del)
        {
            d_was[id] = -1;
            kill(sum_[id]);
            kill(prev_[id]);
            kill(next_[id]);
        }
    }
};

struct prog
{
    int start, diff, len;

    int get (int id) const
    {
        return start + diff * id;
    }

    int get_end () const
    {
        return start + diff * (len - 1);
    }
};

// poor man OOP starting :)
void relax (vector<prog> &v)
{
        vector<prog> nv;

            for (const auto &pr : v)
                    {
                                if (pr.len == 0)
                                                continue;

                                        if (nv.empty())
                                                        nv.pb(pr);
                                                else
                                                            {
                                                                            auto &top = nv.back();
                                                                                if (top.len == 1 && pr.len == 1)
                                                                                top = prog{top.start, pr.start - top.start, 2};
                                                                                else if (top.len == 1 && pr.start - top.start == pr.diff)
                                                                                {
                                                                                top = prog{top.start, pr.diff, pr.len + 1};
                                                                                }
                                                                                else if (pr.len == 1 && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len++;
                                                                                }
                                                                                else if (pr.diff == top.diff && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len += pr.len;
                                                                                }
                                                                                else
                                                                                {
                                                                                nv.pb(pr);
                                                                                }
                                                                                }
                                                    }

                v.swap(nv);
}

void incr_all (vector<prog> &v, int delta)
{
    for (auto &pr : v)
        pr.start += delta;
}

void add_start (vector<prog> &v, int num)
{
    assert(v.empty() || num < v.front().start);
    v.insert(v.begin(), prog{num, 1, 1});
}

void del (vector<prog> &v, const vi &who)
{
    int ptr = 0;
    vector<prog> nv;

    for (const auto &pr : v)
    {
        int last_alive = 0;
        while (ptr < sz(who) && pr.start <= who[ptr] && who[ptr] <= pr.get_end())
        {
            assert((who[ptr] - pr.start) % pr.diff == 0);
            int cur_id = (who[ptr] - pr.start) / pr.diff;
            if (last_alive < cur_id)
                nv.pb(prog{pr.get(last_alive), pr.diff, cur_id - last_alive});

            assert(last_alive <= cur_id);
            last_alive = cur_id + 1;
            ptr++;
        }

        const int total = pr.len;
        if (last_alive < total)
            nv.pb(prog{pr.get(last_alive), pr.diff, total - last_alive});
    }

    v.swap(nv);
    relax(v);
}

void print (const vector<prog> &v)
{
    for (const auto &pr : v)
    {
        forn (i, pr.len)
            eprintf("%d ", pr.get(i));
    }
    eprintf("\n");
}

double time ()
{
    return (double)clock() / CLOCKS_PER_SEC;
}

int work_old() {
        const int n = sz(s) / 2;
            assert(sz(s) == 2 * n);

                vi dp(n + 1);
                    dp[0] = 1;

                        vi pref;

                            forn (len, n + 1) if (len)
                                    {
                                            if (sz(pref) >= 50)
                                                return -1;

                                                const int l = n - len, r = n + len;

                                                        vi npref;
                                                                for (int i : pref)
                                                                            {
                                                                                if (s[l] == s[r - i - 2] && s[l + i + 1] == s[r - 1] && i + 2 <= len)
                                                                                npref.pb(i + 2);
                                                                                }

                                                                        if (s[l] == s[r - 1])
                                                                                npref.pb(1);
                                                                                if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
                                                                                npref.pb(2);

                                                                                pref = npref;
                                                                                /*
                                                                                *         eprintf("for len = %d\n", len);
                                                                                *                 for (int x : pref)
                                                                                *                             eprintf("%d ", x);
                                                                                *                                     eprintf("\n");
                                                                                *                                     */
                                                                                for (int i : pref)
                                                                                add(dp[len], dp[len - i]);
                                                                                }

                                return dp[n];
}

void solve() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    int ans = work_old ();
    if (ans != -1)
    {
        cout << ans << endl;
        return;
    }

    gap_jumper info(s, n);

    vi dp(n + 1);
    dp[0] = 1;
    info.value[0] = 1;

    vector<prog> pref;

    int max = get_max();

    forn (len, n + 1) if (len)
    {
        const int l = n - len, r = n + len;

        vi to_del;

        for (const auto &pr : pref)
        {
            for (int i = 0; i < pr.len; )
            {
                int cur = pr.get(i);
                const int left_steps = info.first_left(r - cur - 2, pr.diff, s[l]);
                const int right_steps = info.first_right(l + cur + 1, pr.diff, s[r - 1]);
                const int steps = min(left_steps, right_steps);

                i += steps;
                if (i >= pr.len)
                    break;

                cur = pr.get(i);
                assert(!(s[l] == s[r - cur - 2] && s[l + cur + 1] == s[r - 1]));
                to_del.pb(cur);
                i++;
            }
        }

        if (!pref.empty() && pref.back().get_end() == len - 1 && !count(all(to_del), len - 1))
            to_del.pb(len - 1);

        del(pref, to_del);

        incr_all(pref, 2);

        if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
            add_start(pref, 2);
        if (s[l] == s[r - 1])
            add_start(pref, 1);

        relax(pref);
        assert(sz(pref) <= 20);

//        eprintf("for len = %d:\n", len);
//        print(pref);

        for (const auto &pr : pref)
        {
            int start = len - pr.get_end();
            int cur_sum = info.sum(start, pr.diff, pr.len);
            add(dp[len], cur_sum);
        }

        vi allowed;
        for (const auto &pr : pref)
            allowed.pb(pr.diff);
        sort(all(allowed));
        allowed.resize(unique(all(allowed)) - allowed.begin());

        info.value[len] = dp[len];
    }

    cout << dp[n] << endl;
}

int main() {
#ifdef LOCAL
    freopen(FILE_NAME ".in", "r", stdin);
//    freopen(FILE_NAME ".out", "w", stdout);
#endif

    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (read()) {
        solve();
//        break;
    }

    return 0;
}


#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define forab(i, a, b) for (int i = int(a); i < int(b); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define fst first
#define snd second

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pii = pair<int, int>;
using vvi = vector<vi>;
using vii = vector<pii>;

#ifdef LOCAL
#define eprintf(args...) fprintf(stderr, args), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define FILE_NAME "a"

string s;

bool read() {
    if (!(cin >> s)) {
        return 0;
    }
    return 1;
}

const int mod = (int) 1e9 + 7;

void add(int &a, int b) {
    a += b;
    if (a >= mod)
        a -= mod;
}

void sub(int &a, int b) {
    a -= b;
    if (a < 0)
        a += mod;
}

void kill(vi &v) {
    v.clear();
    v.shrink_to_fit();
}

struct gap_jumper {
    string s;
    vi value;
    int n;

    gap_jumper(string s_, int n_) {
        n = n_;
        value.resize(n + 1);
        s = s_;
        assert(sz(s) == 2 * n);
    }

    vi d_was;
    vvi next_, prev_, sum_;

    int get_id(int step) {
        int pos = find(all(d_was), step) - d_was.begin();
        if (pos != sz(d_was))
            return pos;

        d_was.pb(step);
        next_.pb(vi(2 * n)), prev_.pb(vi(2 * n)), sum_.pb(vi());
        sum_.back().reserve(n);

        vi &next = next_.back();
        vi &prev = prev_.back();

        ford (i, 2 * n) {
            if (i + step >= 2 * n)
                next[i] = 1;
            else
                next[i] = (s[i] != s[i + step] ? 1 : next[i + step] + 1);
        }

        forn (i, 2 * n) {
            if (i < step)
                prev[i] = 1;
            else
                prev[i] = (s[i] != s[i - step] ? 1 : prev[i - step] + 1);
        }

        return pos;
    }

    int first_left(int pos, int step, char what) {
        const int id = get_id(step);
        const vi &prev = prev_[id];

        if (what != s[pos])
            return 0;
        return prev[pos];
    }

    int first_right(int pos, int step, char what) {
        const int id = get_id(step);
        const vi &next = next_[id];

        if (what != s[pos])
            return 0;
        return next[pos];
    }

    int sum(int pos, int step, int len) {
        const int id = get_id(step);
        vi &sum = sum_[id];

        int to = pos + step * (len - 1);
        assert(0 <= pos && pos <= to && to < sz(value));

        while (sz(sum) <= to) {
            const int cur_id = sz(sum);
            sum.pb(value[cur_id]);
            if (cur_id >= step)
                add(sum.back(), sum[cur_id - step]);
        }

        int res = sum[to];
        if (pos - step >= 0)
            sub(res, sum[pos - step]);

        return res;
    }
};

struct prog {
    int start, diff, len;

    int get(int id) const {
        return start + diff * id;
    }

    int get_end() const {
        return start + diff * (len - 1);
    }
};

// poor man OOP starting :)
void relax(vector<prog> &v) {
    vector<prog> nv;

    for (const auto &pr : v) {
        if (pr.len == 0)
            continue;

        if (nv.empty())
            nv.pb(pr);
        else {
            auto &top = nv.back();
            if (top.len == 1 && pr.len == 1)
                top = prog{top.start, pr.start - top.start, 2};
            else if (top.len == 1 && pr.start - top.start == pr.diff) {
                top = prog{top.start, pr.diff, pr.len + 1};
            } else if (pr.len == 1 && pr.start - top.get_end() == top.diff) {
                top.len++;
            } else if (pr.diff == top.diff && pr.start - top.get_end() == top.diff) {
                top.len += pr.len;
            } else {
                nv.pb(pr);
            }
        }
    }

    v.swap(nv);
}

void incr_all(vector<prog> &v, int delta) {
    for (auto &pr : v)
        pr.start += delta;
}

void add_start(vector<prog> &v, int num) {
    assert(v.empty() || num < v.front().start);
    v.insert(v.begin(), prog{num, 1, 1});
}

void del(vector<prog> &v, const vi &who) {
    int ptr = 0;
    vector<prog> nv;

    for (const auto &pr : v) {
        int last_alive = 0;
        while (ptr < sz(who) && pr.start <= who[ptr] && who[ptr] <= pr.get_end()) {
            assert((who[ptr] - pr.start) % pr.diff == 0);
            int cur_id = (who[ptr] - pr.start) / pr.diff;
            if (last_alive < cur_id)
                nv.pb(prog{pr.get(last_alive), pr.diff, cur_id - last_alive});

            assert(last_alive <= cur_id);
            last_alive = cur_id + 1;
            ptr++;
        }

        const int total = pr.len;
        if (last_alive < total)
            nv.pb(prog{pr.get(last_alive), pr.diff, total - last_alive});
    }

    v.swap(nv);
    relax(v);
}

void print(const vector<prog> &v) {
    for (const auto &pr : v) {
        forn (i, pr.len) eprintf("%d ", pr.get(i));
    }
    eprintf("\n");
}

double time() {
    return (double) clock() / CLOCKS_PER_SEC;
}

int work_old() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    vi dp(n + 1);
    dp[0] = 1;

    vi pref;

    forn (len, n + 1) if (len) {
            if (sz(pref) >= 50)
                return -1;

            const int l = n - len, r = n + len;

            vi npref;
            for (int i : pref) {
                if (s[l] == s[r - i - 2] && s[l + i + 1] == s[r - 1] && i + 2 <= len)
                    npref.pb(i + 2);
            }

            if (s[l] == s[r - 1])
                npref.pb(1);
            if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
                npref.pb(2);

            pref = npref;

            for (int i : pref)
                add(dp[len], dp[len - i]);
        }

    return dp[n];
}

void solve() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    int ans = work_old();
    if (ans != -1) {
        cout << ans << endl;
        return;
    }

    gap_jumper info(s, n);

    vi dp(n + 1);
    dp[0] = 1;
    info.value[0] = 1;

    vector<prog> pref;

    forn (len, n + 1) if (len) {
            const int l = n - len, r = n + len;
            vi to_del;

            for (const auto &pr : pref) {
                for (int i = 0; i < pr.len;) {
                    int cur = pr.get(i);
                    const int left_steps = info.first_left(r - cur - 2, pr.diff, s[l]);
                    const int right_steps = info.first_right(l + cur + 1, pr.diff, s[r - 1]);
                    const int steps = min(left_steps, right_steps);

                    i += steps;
                    if (i >= pr.len)
                        break;

                    cur = pr.get(i);
                    assert(!(s[l] == s[r - cur - 2] && s[l + cur + 1] == s[r - 1]));
                    to_del.pb(cur);
                    i++;
                }
            }

            if (!pref.empty() && pref.back().get_end() == len - 1 && !count(all(to_del), len - 1))
                to_del.pb(len - 1);

            del(pref, to_del);

            incr_all(pref, 2);

            if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
                add_start(pref, 2);
            if (s[l] == s[r - 1])
                add_start(pref, 1);

            relax(pref);
            assert(sz(pref) <= 20);

            for (const auto &pr : pref) {
                int start = len - pr.get_end();
                int cur_sum = info.sum(start, pr.diff, pr.len);
                add(dp[len], cur_sum);
            }

            vi allowed;
            for (const auto &pr : pref)
                allowed.pb(pr.diff);
            sort(all(allowed));
            allowed.resize(unique(all(allowed)) - allowed.begin());

            info.value[len] = dp[len];
        }

    cout << dp[n] << endl;
}

int main() {
#ifdef LOCAL
//    freopen(FILE_NAME ".in", "r", stdin);
//    freopen(FILE_NAME ".out", "w", stdout);
#endif

    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (read()) {
        solve();
//        break;
    }

    return 0;
}


#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define forab(i, a, b) for (int i = int(a); i < int(b); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define fst first
#define snd second

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pii = pair<int, int>;
using vvi = vector<vi>;
using vii = vector<pii>;

#ifdef LOCAL
#define eprintf(args...) fprintf(stderr, args), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define FILE_NAME "a"

string s;

bool read() {
    if (!(cin >> s)) {
        return 0;
    }
    return 1;
}

const int mod = (int)1e9 + 7;

void add (int &a, int b)
{
    a += b;
    if (a >= mod)
        a -= mod;
}

void sub (int &a, int b)
{
    a -= b;
    if (a < 0)
        a += mod;
}

void kill (vi &v)
{
    v.clear();
    v.shrink_to_fit();
}

struct gap_jumper
{
    string s;
    vi value;
    int n;

    gap_jumper (string s_, int n_)
    {
        n = n_;
        value.resize(n + 1);
        s = s_;
        assert(sz(s) == 2 * n);
    }

    vi d_was;
    vvi next_, prev_, sum_;

    int get_id (int step)
    {

        int pos = find(all(d_was), step) - d_was.begin();
        if (pos != sz(d_was))
            return pos;

        d_was.pb(step);
        next_.pb(vi(2 * n)), prev_.pb(vi(2 * n)), sum_.pb(vi());
        sum_.back().reserve(n);

        vi &next = next_.back();
        vi &prev = prev_.back();

        ford (i, 2 * n)
        {
            if (i + step >= 2 * n)
                next[i] = 1;
            else
                next[i] = (s[i] != s[i + step] ? 1 : next[i + step] + 1);
        }

        forn (i, 2 * n)
        {
            if (i < step)
                prev[i] = 1;
            else
                prev[i] = (s[i] != s[i - step] ? 1 : prev[i - step] + 1);
        }

        return pos;
    }

    int first_left (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &prev = prev_[id];

        if (what != s[pos])
            return 0;
        return prev[pos];
    }

    int first_right (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &next = next_[id];

        if (what != s[pos])
            return 0;
        return next[pos];
    }

    int sum (int pos, int step, int len)
    {
        const int id = get_id(step);
        vi &sum = sum_[id];

        int to = pos + step * (len - 1);
        assert(0 <= pos && pos <= to && to < sz(value));

        while (sz(sum) <= to)
        {
            const int cur_id = sz(sum);
            sum.pb(value[cur_id]);
            if (cur_id >= step)
                add(sum.back(), sum[cur_id - step]);
        }

        int res = sum[to];
        if (pos - step >= 0)
            sub(res, sum[pos - step]);

        return res;
    }

    void purge (const vi &allowed)
    {
        vi to_del;
        forn (i, sz(d_was))
        {
            const int id = d_was[i];
            if (!binary_search(all(allowed), id))
                to_del.pb(i);
        }

        reverse(all(to_del));
        for (int id : to_del)
        {
            d_was[id] = -1;
            kill(sum_[id]);
            kill(prev_[id]);
            kill(next_[id]);
        }
    }
};

struct prog
{
    int start, diff, len;

    int get (int id) const
    {
        return start + diff * id;
    }

    int get_end () const
    {
        return start + diff * (len - 1);
    }
};

// poor man OOP starting :)
void relax (vector<prog> &v)
{
        vector<prog> nv;

            for (const auto &pr : v)
                    {
                                if (pr.len == 0)
                                                continue;

                                        if (nv.empty())
                                                        nv.pb(pr);
                                                else
                                                            {
                                                                            auto &top = nv.back();
                                                                                if (top.len == 1 && pr.len == 1)
                                                                                top = prog{top.start, pr.start - top.start, 2};
                                                                                else if (top.len == 1 && pr.start - top.start == pr.diff)
                                                                                {
                                                                                top = prog{top.start, pr.diff, pr.len + 1};
                                                                                }
                                                                                else if (pr.len == 1 && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len++;
                                                                                }
                                                                                else if (pr.diff == top.diff && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len += pr.len;
                                                                                }
                                                                                else
                                                                                {
                                                                                nv.pb(pr);
                                                                                }
                                                                                }
                                                    }

                v.swap(nv);
}

void incr_all (vector<prog> &v, int delta)
{
    for (auto &pr : v)
        pr.start += delta;
}

void add_start (vector<prog> &v, int num)
{
    assert(v.empty() || num < v.front().start);
    v.insert(v.begin(), prog{num, 1, 1});
}

void del (vector<prog> &v, const vi &who)
{
    int ptr = 0;
    vector<prog> nv;

    for (const auto &pr : v)
    {
        int last_alive = 0;
        while (ptr < sz(who) && pr.start <= who[ptr] && who[ptr] <= pr.get_end())
        {
            assert((who[ptr] - pr.start) % pr.diff == 0);
            int cur_id = (who[ptr] - pr.start) / pr.diff;
            if (last_alive < cur_id)
                nv.pb(prog{pr.get(last_alive), pr.diff, cur_id - last_alive});

            assert(last_alive <= cur_id);
            last_alive = cur_id + 1;
            ptr++;
        }

        const int total = pr.len;
        if (last_alive < total)
            nv.pb(prog{pr.get(last_alive), pr.diff, total - last_alive});
    }

    v.swap(nv);
    relax(v);
}

void print (const vector<prog> &v)
{
    for (const auto &pr : v)
    {
        forn (i, pr.len)
            eprintf("%d ", pr.get(i));
    }
    eprintf("\n");
}

double time ()
{
    return (double)clock() / CLOCKS_PER_SEC;
}

void solve() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    gap_jumper info(s, n);

    vi dp(n + 1);
    dp[0] = 1;
    info.value[0] = 1;

    vector<prog> pref;

    forn (len, n + 1) if (len)
    {
        const int l = n - len, r = n + len;

        vi to_del;

        for (const auto &pr : pref)
        {
            for (int i = 0; i < pr.len; )
            {
                int cur = pr.get(i);
                const int left_steps = info.first_left(r - cur - 2, pr.diff, s[l]);
                const int right_steps = info.first_right(l + cur + 1, pr.diff, s[r - 1]);
                const int steps = min(left_steps, right_steps);

                i += steps;
                if (i >= pr.len)
                    break;

                cur = pr.get(i);
                assert(!(s[l] == s[r - cur - 2] && s[l + cur + 1] == s[r - 1]));
                to_del.pb(cur);
                i++;
            }
        }

        if (!pref.empty() && pref.back().get_end() == len - 1 && !count(all(to_del), len - 1))
            to_del.pb(len - 1);

        del(pref, to_del);

        incr_all(pref, 2);

        if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
            add_start(pref, 2);
        if (s[l] == s[r - 1])
            add_start(pref, 1);

        relax(pref);
        assert(sz(pref) <= 20);

//        eprintf("for len = %d:\n", len);
//        print(pref);

        for (const auto &pr : pref)
        {
            int start = len - pr.get_end();
            int cur_sum = info.sum(start, pr.diff, pr.len);
            add(dp[len], cur_sum);
        }

        vi allowed;
        for (const auto &pr : pref)
            allowed.pb(pr.diff);
        sort(all(allowed));
        allowed.resize(unique(all(allowed)) - allowed.begin());

        if (len % 100 == 0 && time() <= 1.5)
            info.purge(allowed);
        info.value[len] = dp[len];
    }

    cout << dp[n] << endl;
}

int main() {
#ifdef LOCAL
    freopen(FILE_NAME ".in", "r", stdin);
//    freopen(FILE_NAME ".out", "w", stdout);
#endif

    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (read()) {
        solve();
//        break;
    }

    return 0;
}


#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define forab(i, a, b) for (int i = int(a); i < int(b); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define fst first
#define snd second

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pii = pair<int, int>;
using vvi = vector<vi>;
using vii = vector<pii>;

#ifdef LOCAL
#define eprintf(args...) fprintf(stderr, args), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define FILE_NAME "a"

string s;

bool read() {
    if (!(cin >> s)) {
        return 0;
    }
    return 1;
}

const int mod = (int)1e9 + 7;

void add (int &a, int b)
{
    a += b;
    if (a >= mod)
        a -= mod;
}

void sub (int &a, int b)
{
    a -= b;
    if (a < 0)
        a += mod;
}

void kill (vi &v)
{
    v.clear();
    v.shrink_to_fit();
}

struct gap_jumper
{
    string s;
    vi value;
    int n;

    gap_jumper (string s_, int n_)
    {
        n = n_;
        value.resize(n + 1);
        s = s_;
        assert(sz(s) == 2 * n);
    }

    vi d_was;
    vvi next_, prev_, sum_;

    int get_id (int step)
    {

        int pos = find(all(d_was), step) - d_was.begin();
        if (pos != sz(d_was))
            return pos;

        d_was.pb(step);
        next_.pb(vi(2 * n)), prev_.pb(vi(2 * n)), sum_.pb(vi());
        sum_.back().reserve(n);

        vi &next = next_.back();
        vi &prev = prev_.back();

        ford (i, 2 * n)
        {
            if (i + step >= 2 * n)
                next[i] = 1;
            else
                next[i] = (s[i] != s[i + step] ? 1 : next[i + step] + 1);
        }

        forn (i, 2 * n)
        {
            if (i < step)
                prev[i] = 1;
            else
                prev[i] = (s[i] != s[i - step] ? 1 : prev[i - step] + 1);
        }

        return pos;
    }

    int first_left (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &prev = prev_[id];

        if (what != s[pos])
            return 0;
        return prev[pos];
    }

    int first_right (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &next = next_[id];

        if (what != s[pos])
            return 0;
        return next[pos];
    }

    int sum (int pos, int step, int len)
    {
        const int id = get_id(step);
        vi &sum = sum_[id];

        int to = pos + step * (len - 1);
        assert(0 <= pos && pos <= to && to < sz(value));

        while (sz(sum) <= to)
        {
            const int cur_id = sz(sum);
            sum.pb(value[cur_id]);
            if (cur_id >= step)
                add(sum.back(), sum[cur_id - step]);
        }

        int res = sum[to];
        if (pos - step >= 0)
            sub(res, sum[pos - step]);

        return res;
    }

    void purge (const vi &allowed)
    {
        vi to_del;
        forn (i, sz(d_was))
        {
            const int id = d_was[i];
            if (!binary_search(all(allowed), id))
                to_del.pb(i);
        }

        reverse(all(to_del));
        for (int id : to_del)
        {
            d_was[id] = -1;
            kill(sum_[id]);
            kill(prev_[id]);
            kill(next_[id]);
        }
    }
};

struct prog
{
    int start, diff, len;

    int get (int id) const
    {
        return start + diff * id;
    }

    int get_end () const
    {
        return start + diff * (len - 1);
    }
};

// poor man OOP starting :)
void relax (vector<prog> &v)
{
        vector<prog> nv;

            for (const auto &pr : v)
                    {
                                if (pr.len == 0)
                                                continue;

                                        if (nv.empty())
                                                        nv.pb(pr);
                                                else
                                                            {
                                                                            auto &top = nv.back();
                                                                                if (top.len == 1 && pr.len == 1)
                                                                                top = prog{top.start, pr.start - top.start, 2};
                                                                                else if (top.len == 1 && pr.start - top.start == pr.diff)
                                                                                {
                                                                                top = prog{top.start, pr.diff, pr.len + 1};
                                                                                }
                                                                                else if (pr.len == 1 && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len++;
                                                                                }
                                                                                else if (pr.diff == top.diff && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len += pr.len;
                                                                                }
                                                                                else
                                                                                {
                                                                                nv.pb(pr);
                                                                                }
                                                                                }
                                                    }

                v.swap(nv);
}

void incr_all (vector<prog> &v, int delta)
{
    for (auto &pr : v)
        pr.start += delta;
}

void add_start (vector<prog> &v, int num)
{
    assert(v.empty() || num < v.front().start);
    v.insert(v.begin(), prog{num, 1, 1});
}

void del (vector<prog> &v, const vi &who)
{
    int ptr = 0;
    vector<prog> nv;

    for (const auto &pr : v)
    {
        int last_alive = 0;
        while (ptr < sz(who) && pr.start <= who[ptr] && who[ptr] <= pr.get_end())
        {
            assert((who[ptr] - pr.start) % pr.diff == 0);
            int cur_id = (who[ptr] - pr.start) / pr.diff;
            if (last_alive < cur_id)
                nv.pb(prog{pr.get(last_alive), pr.diff, cur_id - last_alive});

            assert(last_alive <= cur_id);
            last_alive = cur_id + 1;
            ptr++;
        }

        const int total = pr.len;
        if (last_alive < total)
            nv.pb(prog{pr.get(last_alive), pr.diff, total - last_alive});
    }

    v.swap(nv);
    relax(v);
}

void print (const vector<prog> &v)
{
    for (const auto &pr : v)
    {
        forn (i, pr.len)
            eprintf("%d ", pr.get(i));
    }
    eprintf("\n");
}

void solve() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    gap_jumper info(s, n);

    vi dp(n + 1);
    dp[0] = 1;
    info.value[0] = 1;

    vector<prog> pref;

    forn (len, n + 1) if (len)
    {
        const int l = n - len, r = n + len;

        vi to_del;

        for (const auto &pr : pref)
        {
            for (int i = 0; i < pr.len; )
            {
                int cur = pr.get(i);
                const int left_steps = info.first_left(r - cur - 2, pr.diff, s[l]);
                const int right_steps = info.first_right(l + cur + 1, pr.diff, s[r - 1]);
                const int steps = min(left_steps, right_steps);

                i += steps;
                if (i >= pr.len)
                    break;

                cur = pr.get(i);
                assert(!(s[l] == s[r - cur - 2] && s[l + cur + 1] == s[r - 1]));
                to_del.pb(cur);
                i++;
            }
        }

        if (!pref.empty() && pref.back().get_end() == len - 1 && !count(all(to_del), len - 1))
            to_del.pb(len - 1);

        del(pref, to_del);

        incr_all(pref, 2);

        if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
            add_start(pref, 2);
        if (s[l] == s[r - 1])
            add_start(pref, 1);

        relax(pref);
        assert(sz(pref) <= 20);

//        eprintf("for len = %d:\n", len);
//        print(pref);

        for (const auto &pr : pref)
        {
            int start = len - pr.get_end();
            int cur_sum = info.sum(start, pr.diff, pr.len);
            add(dp[len], cur_sum);
        }

        vi allowed;
        for (const auto &pr : pref)
            allowed.pb(pr.diff);
        sort(all(allowed));
        allowed.resize(unique(all(allowed)) - allowed.begin());

        if (len % 10 == 0)
            info.purge(allowed);
        info.value[len] = dp[len];
    }

    cout << dp[n] << endl;
}

int main() {
#ifdef LOCAL
    freopen(FILE_NAME ".in", "r", stdin);
//    freopen(FILE_NAME ".out", "w", stdout);
#endif

    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (read()) {
        solve();
//        break;
    }

    return 0;
}


#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define forab(i, a, b) for (int i = int(a); i < int(b); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define fst first
#define snd second

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pii = pair<int, int>;
using vvi = vector<vi>;
using vii = vector<pii>;

#ifdef LOCAL
#define eprintf(args...) fprintf(stderr, args), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define FILE_NAME "a"

string s;

bool read() {
    if (!(cin >> s)) {
        return 0;
    }
    return 1;
}

const int mod = (int)1e9 + 7;

void add (int &a, int b)
{
    a += b;
    if (a >= mod)
        a -= mod;
}

void sub (int &a, int b)
{
    a -= b;
    if (a < 0)
        a += mod;
}

void kill (vi &v)
{
    v.clear();
    v.shrink_to_fit();
}

struct gap_jumper
{
    string s;
    vi value;
    int n;

    gap_jumper (string s_, int n_)
    {
        n = n_;
        value.resize(n + 1);
        s = s_;
        assert(sz(s) == 2 * n);
    }

    vi d_was;
    vvi next_, prev_, sum_;

    int get_id (int step)
    {

        int pos = find(all(d_was), step) - d_was.begin();
        if (pos != sz(d_was))
            return pos;

        d_was.pb(step);
        next_.pb(vi(2 * n)), prev_.pb(vi(2 * n)), sum_.pb(vi());
        sum_.back().reserve(n);

        vi &next = next_.back();
        vi &prev = prev_.back();

        ford (i, 2 * n)
        {
            if (i + step >= 2 * n)
                next[i] = 1;
            else
                next[i] = (s[i] != s[i + step] ? 1 : next[i + step] + 1);
        }

        forn (i, 2 * n)
        {
            if (i < step)
                prev[i] = 1;
            else
                prev[i] = (s[i] != s[i - step] ? 1 : prev[i - step] + 1);
        }

        return pos;
    }

    int first_left (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &prev = prev_[id];

        if (what != s[pos])
            return 0;
        return prev[pos];
    }

    int first_right (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &next = next_[id];

        if (what != s[pos])
            return 0;
        return next[pos];
    }

    int sum (int pos, int step, int len)
    {
        const int id = get_id(step);
        vi &sum = sum_[id];

        int to = pos + step * (len - 1);
        assert(0 <= pos && pos <= to && to < sz(value));

        while (sz(sum) <= to)
        {
            const int cur_id = sz(sum);
            sum.pb(value[cur_id]);
            if (cur_id >= step)
                add(sum.back(), sum[cur_id - step]);
        }

        int res = sum[to];
        if (pos - step >= 0)
            sub(res, sum[pos - step]);

        return res;
    }

    void purge (const vi &allowed)
    {
        vi to_del;
        forn (i, sz(d_was))
        {
            const int id = d_was[i];
            if (!binary_search(all(allowed), id))
                to_del.pb(i);
        }

        reverse(all(to_del));
        for (int id : to_del)
        {
            d_was[id] = -1;
            kill(sum_[id]);
            kill(prev_[id]);
            kill(next_[id]);
        }
    }
};

struct prog
{
    int start, diff, len;

    int get (int id) const
    {
        return start + diff * id;
    }

    int get_end () const
    {
        return start + diff * (len - 1);
    }
};

// poor man OOP starting :)
void relax (vector<prog> &v)
{
        vector<prog> nv;

            for (const auto &pr : v)
                    {
                                if (pr.len == 0)
                                                continue;

                                        if (nv.empty())
                                                        nv.pb(pr);
                                                else
                                                            {
                                                                            auto &top = nv.back();
                                                                                if (top.len == 1 && pr.len == 1)
                                                                                top = prog{top.start, pr.start - top.start, 2};
                                                                                else if (top.len == 1 && pr.start - top.start == pr.diff)
                                                                                {
                                                                                top = prog{top.start, pr.diff, pr.len + 1};
                                                                                }
                                                                                else if (pr.len == 1 && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len++;
                                                                                }
                                                                                else if (pr.diff == top.diff && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len += pr.len;
                                                                                }
                                                                                else
                                                                                {
                                                                                nv.pb(pr);
                                                                                }
                                                                                }
                                                    }

                v.swap(nv);
}

void incr_all (vector<prog> &v, int delta)
{
    for (auto &pr : v)
        pr.start += delta;
}

void add_start (vector<prog> &v, int num)
{
    assert(v.empty() || num < v.front().start);
    v.insert(v.begin(), prog{num, 1, 1});
}

void del (vector<prog> &v, const vi &who)
{
    int ptr = 0;
    vector<prog> nv;

    for (const auto &pr : v)
    {
        int last_alive = 0;
        while (ptr < sz(who) && pr.start <= who[ptr] && who[ptr] <= pr.get_end())
        {
            assert((who[ptr] - pr.start) % pr.diff == 0);
            int cur_id = (who[ptr] - pr.start) / pr.diff;
            if (last_alive < cur_id)
                nv.pb(prog{pr.get(last_alive), pr.diff, cur_id - last_alive});

            assert(last_alive <= cur_id);
            last_alive = cur_id + 1;
            ptr++;
        }

        const int total = pr.len;
        if (last_alive < total)
            nv.pb(prog{pr.get(last_alive), pr.diff, total - last_alive});
    }

    v.swap(nv);
    relax(v);
}

void print (const vector<prog> &v)
{
    for (const auto &pr : v)
    {
        forn (i, pr.len)
            eprintf("%d ", pr.get(i));
    }
    eprintf("\n");
}

double time ()
{
    return (double)clock() / CLOCKS_PER_SEC;
}

void solve() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    gap_jumper info(s, n);

    vi dp(n + 1);
    dp[0] = 1;
    info.value[0] = 1;

    vector<prog> pref;

    forn (len, n + 1) if (len)
    {
        const int l = n - len, r = n + len;

        vi to_del;

        for (const auto &pr : pref)
        {
            for (int i = 0; i < pr.len; )
            {
                int cur = pr.get(i);
                const int left_steps = info.first_left(r - cur - 2, pr.diff, s[l]);
                const int right_steps = info.first_right(l + cur + 1, pr.diff, s[r - 1]);
                const int steps = min(left_steps, right_steps);

                i += steps;
                if (i >= pr.len)
                    break;

                cur = pr.get(i);
                assert(!(s[l] == s[r - cur - 2] && s[l + cur + 1] == s[r - 1]));
                to_del.pb(cur);
                i++;
            }
        }

        if (!pref.empty() && pref.back().get_end() == len - 1 && !count(all(to_del), len - 1))
            to_del.pb(len - 1);

        del(pref, to_del);

        incr_all(pref, 2);

        if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
            add_start(pref, 2);
        if (s[l] == s[r - 1])
            add_start(pref, 1);

        relax(pref);
        assert(sz(pref) <= 20);

//        eprintf("for len = %d:\n", len);
//        print(pref);

        for (const auto &pr : pref)
        {
            int start = len - pr.get_end();
            int cur_sum = info.sum(start, pr.diff, pr.len);
            add(dp[len], cur_sum);
        }

        vi allowed;
        for (const auto &pr : pref)
            allowed.pb(pr.diff);
        sort(all(allowed));
        allowed.resize(unique(all(allowed)) - allowed.begin());

        if (len % 100 == 0 && time() <= 2.5)
            info.purge(allowed);
        info.value[len] = dp[len];
    }

    cout << dp[n] << endl;
}

int main() {
#ifdef LOCAL
    freopen(FILE_NAME ".in", "r", stdin);
//    freopen(FILE_NAME ".out", "w", stdout);
#endif

    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (read()) {
        solve();
//        break;
    }

    return 0;
}


#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define forab(i, a, b) for (int i = int(a); i < int(b); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define fst first
#define snd second

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pii = pair<int, int>;
using vvi = vector<vi>;
using vii = vector<pii>;

#ifdef LOCAL
#define eprintf(args...) fprintf(stderr, args), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define FILE_NAME "a"

string s;

bool read() {
    if (!(cin >> s)) {
        return 0;
    }
    return 1;
}

const int mod = (int)1e9 + 7;

void add (int &a, int b)
{
    a += b;
    if (a >= mod)
        a -= mod;
}

void sub (int &a, int b)
{
    a -= b;
    if (a < 0)
        a += mod;
}

struct gap_jumper
{
    string s;
    vi value;
    int n;

    gap_jumper (string s_, int n_)
    {
        n = n_;
        value.resize(n + 1);
        s = s_;
        assert(sz(s) == 2 * n);
    }

    vi d_was;
    vvi next_, prev_, sum_;

    int get_id (int step)
    {

        int pos = find(all(d_was), step) - d_was.begin();
        if (pos != sz(d_was))
            return pos;

        d_was.pb(step);
        next_.pb(vi(2 * n)), prev_.pb(vi(2 * n)), sum_.pb(vi());

        vi &next = next_.back();
        vi &prev = prev_.back();

        ford (i, 2 * n)
        {
            if (i + step >= 2 * n)
                next[i] = 1;
            else
                next[i] = (s[i] != s[i + step] ? 1 : next[i + step] + 1);
        }

        forn (i, 2 * n)
        {
            if (i < step)
                prev[i] = 1;
            else
                prev[i] = (s[i] != s[i - step] ? 1 : prev[i - step] + 1);
        }

        return pos;
    }

    int first_left (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &prev = prev_[id];

        if (what != s[pos])
            return 0;
        return prev[pos];
    }

    int first_right (int pos, int step, char what)
    {
        const int id = get_id(step);
        const vi &next = next_[id];

        if (what != s[pos])
            return 0;
        return next[pos];
    }

    int sum (int pos, int step, int len)
    {

        const int id = get_id(step);
        vi &sum = sum_[id];

        int to = pos + step * (len - 1);
        assert(0 <= pos && pos <= to && to < sz(value));

        while (sz(sum) <= to)
        {
            const int cur_id = sz(sum);
            sum.pb(value[cur_id]);
            if (cur_id >= step)
                add(sum.back(), sum[cur_id - step]);
        }

        int res = sum[to];
        if (pos - step >= 0)
            sub(res, sum[pos - step]);

        return res;
    }
};

struct prog
{
    int start, diff, len;

    int get (int id) const
    {
        return start + diff * id;
    }

    int get_end () const
    {
        return start + diff * (len - 1);
    }
};

// poor man OOP starting :)
void relax (vector<prog> &v)
{
        vector<prog> nv;

            for (const auto &pr : v)
                    {
                                if (pr.len == 0)
                                                continue;

                                        if (nv.empty())
                                                        nv.pb(pr);
                                                else
                                                            {
                                                                            auto &top = nv.back();
                                                                                if (top.len == 1 && pr.len == 1)
                                                                                top = prog{top.start, pr.start - top.start, 2};
                                                                                else if (top.len == 1 && pr.start - top.start == pr.diff)
                                                                                {
                                                                                top = prog{top.start, pr.diff, pr.len + 1};
                                                                                }
                                                                                else if (pr.len == 1 && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len++;
                                                                                }
                                                                                else if (pr.diff == top.diff && pr.start - top.get_end() == top.diff)
                                                                                {
                                                                                top.len += pr.len;
                                                                                }
                                                                                else
                                                                                {
                                                                                nv.pb(pr);
                                                                                }
                                                                                }
                                                    }

                v.swap(nv);
}

void incr_all (vector<prog> &v, int delta)
{
    for (auto &pr : v)
        pr.start += delta;
}

void add_start (vector<prog> &v, int num)
{
    assert(v.empty() || num < v.front().start);
    v.insert(v.begin(), prog{num, 1, 1});
}

void del (vector<prog> &v, const vi &who)
{
    int ptr = 0;
    vector<prog> nv;

    for (const auto &pr : v)
    {
        int last_alive = 0;
        while (ptr < sz(who) && pr.start <= who[ptr] && who[ptr] <= pr.get_end())
        {
            assert((who[ptr] - pr.start) % pr.diff == 0);
            int cur_id = (who[ptr] - pr.start) / pr.diff;
            if (last_alive < cur_id)
                nv.pb(prog{pr.get(last_alive), pr.diff, cur_id - last_alive});

            assert(last_alive <= cur_id);
            last_alive = cur_id + 1;
            ptr++;
        }

        const int total = pr.len;
        if (last_alive < total)
            nv.pb(prog{pr.get(last_alive), pr.diff, total - last_alive});
    }

    v.swap(nv);
    relax(v);
}

void print (const vector<prog> &v)
{
    for (const auto &pr : v)
    {
        forn (i, pr.len)
            eprintf("%d ", pr.get(i));
    }
    eprintf("\n");
}

void solve() {
    const int n = sz(s) / 2;
    assert(sz(s) == 2 * n);

    gap_jumper info(s, n);

    vi dp(n + 1);
    dp[0] = 1;
    info.value[0] = 1;

    vector<prog> pref;

    forn (len, n + 1) if (len)
    {
        const int l = n - len, r = n + len;

        vi to_del;

        for (const auto &pr : pref)
        {
            for (int i = 0; i < pr.len; )
            {
                int cur = pr.get(i);
                const int left_steps = info.first_left(r - cur - 2, pr.diff, s[l]);
                const int right_steps = info.first_right(l + cur + 1, pr.diff, s[r - 1]);
                const int steps = min(left_steps, right_steps);

                i += steps;
                if (i >= pr.len)
                    break;

                cur = pr.get(i);
                assert(!(s[l] == s[r - cur - 2] && s[l + cur + 1] == s[r - 1]));
                to_del.pb(cur);
                i++;
            }
        }

        if (!pref.empty() && pref.back().get_end() == len - 1 && !count(all(to_del), len - 1))
            to_del.pb(len - 1);

        del(pref, to_del);

        incr_all(pref, 2);

        if (len >= 2 && s[l] == s[r - 2] && s[l + 1] == s[r - 1])
            add_start(pref, 2);
        if (s[l] == s[r - 1])
            add_start(pref, 1);

        relax(pref);

//        eprintf("for len = %d:\n", len);
//        print(pref);

        for (const auto &pr : pref)
        {
            int start = len - pr.get_end();
            int cur_sum = info.sum(start, pr.diff, pr.len);
            add(dp[len], cur_sum);
        }

        info.value[len] = dp[len];
    }

    cout << dp[n] << endl;
}

int main() {
#ifdef LOCAL
    freopen(FILE_NAME ".in", "r", stdin);
//    freopen(FILE_NAME ".out", "w", stdout);
#endif

    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (read()) {
        solve();
//        break;
    }

    return 0;
}