#include <bits/stdc++.h>

using namespace std;

typedef unsigned int ui;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<long long, long long> pll;
typedef long double ld;

const int inf = 1e9;
const ll inf64 = 1e18;

const int mod = inf + 7;

inline int _sum(int a, int b) {
    return a + b < mod ? a + b : a + b - mod;
}

inline int _mul(int a, int b) {
    return (1ll * a * b) % mod;
}

inline int _sub(int a, int b) {
    return a >= b ? a - b : a - b + mod;
}

inline void _inc(int &x, int y) {
    if ((x += y) >= mod) {
        x -= mod;
    }
}

inline void _dec(int &x, int y) {
    if ((x -= y) < 0) {
        x += mod;
    }
}

inline int _binpow(int x, int pw) {
    int res = 1;
    int tmp = x;
    while (pw > 0) {
        if (pw & 1) {
            res = _mul(res, tmp);
        }
        tmp = _mul(tmp, tmp);
        pw >>= 1;
    }
    return res;
}

inline int _div(int a, int b) {
    return _mul(a, _binpow(b, mod - 2));
}

void read(string& s) {
    cin >> s;
}

void gen(string& s) {
    mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
    int n = 2 * (rnd() % 3 + 1);
    s.resize(n, '?');
    for (int i = 0; i < n; i++) {
        s[i] = rnd() % 5 == 0 ? 'a' : 'b';
    }
}

string join_halfs(string s) {
    int n = (int) s.size();
    string t;
    for (int i = 0; i < n / 2; i++) {
        t.push_back(s[i]);
        t.push_back(s[n - 1 - i]);
    }
    return t;
}

int slow(string s) {
    s = join_halfs(s);
    int n = (int) s.size();
    s = "#" + s;
    vector<int> dp(n + 1);
    dp[0] = 1;
    cout << s << "\n";
    for (int i = 1; i <= n; i++) {
        for (int j = i; j >= 1; j--) {
            if ((i - j + 1) % 2) continue;
            string hlp = s.substr(j, i - j + 1);
            string rhlp = hlp; reverse(rhlp.begin(), rhlp.end());
            if (hlp == rhlp) {
                _inc(dp[i], dp[j - 1]);
            }
        }
    }
    return dp[n];
}

const int N = 2e6 + 5;

struct EerTree {
    char s[N];
    int n;
    int sz;
    int link[N];
    int len[N];
    map<char, int> nxt[N];
    int diff[N];
    int dp[N][2];
    int slink[N];
    int max_suff;
    int ans[N];

    void clr() {
        fill(s, s + N, 0);
        fill(link, link + N, 0);
        fill(len, len + N, 0);
        fill(nxt, nxt + N, map<char, int>());
        fill(diff, diff + N, 0);
        fill((int*) dp, (int*) dp + N * 2, 0);
        fill(slink, slink + N, 0);
        n = 0;
        sz = 0;
        max_suff = 0;
        fill(ans, ans + N, 0);
    }

    EerTree() {
        clr();
        s[0] = '#'; // not in alphabet
        link[0] = 1;
        link[1] = 0;
        len[0] = -1;
        sz = 2;
        ans[0] = 1;
    }

    int get_link(int from) {
        while (s[n] != s[n - len[from] - 1]) {
            from = link[from];
        }
        return from;
    }

    void add_symbol(char c) {
        s[++n] = c;
        max_suff = get_link(max_suff);
        if (!nxt[max_suff].count(c)) {
            {
                int x = get_link(link[max_suff]);
                link[sz] = nxt[x].count(c) ? nxt[x][c] : 1;
            }
            len[sz] = len[max_suff] + 2;
            diff[sz] = len[sz] - len[link[sz]];
            slink[sz] = diff[sz] == diff[link[sz]] ? slink[link[sz]] : link[sz];
            nxt[max_suff][c] = sz++;
        }
        max_suff = nxt[max_suff][c];
        for (int x = max_suff; len[x] > 0; x = slink[x]) {
            dp[x][0] = dp[x][1] = 0;
            int j = n - (len[slink[x]] + diff[x]);
            _inc(dp[x][j & 1], ans[j]);
            if (diff[x] == diff[link[x]]) {
                _inc(dp[x][0], dp[link[x]][0]);
                _inc(dp[x][1], dp[link[x]][1]);
            }
            _inc(ans[n], dp[x][n & 1]);
        }
    }
};

int fast(string s) {
    int n = (int) s.size();
    s = join_halfs(s);
    EerTree eertree;
    for (char c : s) {
        eertree.add_symbol(c);
    }
    return eertree.ans[n];
}

void WORK() {
    string s;
    read(s);
//    cout << slow(s) << "\n";
    cout << fast(s) << "\n";
}

void TEST() {
    while (1) {
        string s;
        gen(s);
        cout << "s = " << s << endl;
        int sl = slow(s);
        int fs = fast(s);
        if (sl == fs) {
            cout << "OK (" << fs << ")" << endl;
        } else {
            cout << "WA" << endl;
            cout << "exp = " << sl << endl;
            cout << "fnd = " << fs << endl;
            break;
        }
    }
}

int main() {

#ifdef debug
    freopen("input.txt", "r", stdin);
#endif

    ios_base::sync_with_stdio(0);
    cin.tie(0);

    WORK();
//    TEST();

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned int ui;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<long long, long long> pll;
typedef long double ld;

const int inf = 1e9;
const ll inf64 = 1e18;

const int mod = inf + 7;

inline int _sum(int a, int b) {
    return a + b < mod ? a + b : a + b - mod;
}

inline int _mul(int a, int b) {
    return (1ll * a * b) % mod;
}

inline int _sub(int a, int b) {
    return a >= b ? a - b : a - b + mod;
}

inline void _inc(int &x, int y) {
    if ((x += y) >= mod) {
        x -= mod;
    }
}

inline void _dec(int &x, int y) {
    if ((x -= y) < 0) {
        x += mod;
    }
}

inline int _binpow(int x, int pw) {
    int res = 1;
    int tmp = x;
    while (pw > 0) {
        if (pw & 1) {
            res = _mul(res, tmp);
        }
        tmp = _mul(tmp, tmp);
        pw >>= 1;
    }
    return res;
}

inline int _div(int a, int b) {
    return _mul(a, _binpow(b, mod - 2));
}

void read(string& s) {
    cin >> s;
}

void gen(string& s) {
    mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
    int n = 2 * (rnd() % 3 + 1);
    s.resize(n, '?');
    for (int i = 0; i < n; i++) {
        s[i] = rnd() % 5 == 0 ? 'a' : 'b';
    }
}

string join_halfs(string s) {
    int n = (int) s.size();
    string t;
    for (int i = 0; i < n / 2; i++) {
        t.push_back(s[i]);
        t.push_back(s[n - 1 - i]);
    }
    return t;
}

int slow(string s) {
    s = join_halfs(s);
    int n = (int) s.size();
    s = "#" + s;
    vector<int> dp(n + 1);
    dp[0] = 1;
    cout << s << "\n";
    for (int i = 1; i <= n; i++) {
        for (int j = i; j >= 1; j--) {
            if ((i - j + 1) % 2) continue;
            string hlp = s.substr(j, i - j + 1);
            string rhlp = hlp; reverse(rhlp.begin(), rhlp.end());
            if (hlp == rhlp) {
                _inc(dp[i], dp[j - 1]);
            }
        }
    }
    return dp[n];
}

const int N = 2e6 + 5;

struct EerTree {
    char s[N];
    int n;
    int sz;
    int link[N];
    int len[N];
    map<char, int> nxt[N];
    int diff[N];
    int dp[N][2];
    int slink[N];
    int max_suff;
    int ans[N];

    void clr() {
        fill(s, s + N, 0);
        fill(link, link + N, 0);
        fill(len, len + N, 0);
        fill(nxt, nxt + N, map<char, int>());
        fill(diff, diff + N, 0);
        fill((int*) dp, (int*) dp + N * 2, 0);
        fill(slink, slink + N, 0);
        n = 0;
        sz = 0;
        max_suff = 0;
        fill(ans, ans + N, 0);
    }

    EerTree() {
        clr();
        s[0] = '#'; // not in alphabet
        link[0] = 1;
        link[1] = 0;
        len[0] = -1;
        max_suff = 1;
        sz = 2;
        ans[0] = 1;
    }

    int get_link(int from) {
        while (s[n] != s[n - len[from] - 1]) {
            from = link[from];
        }
        return from;
    }

    void add_symbol(char c) {
        s[++n] = c;
        max_suff = get_link(max_suff);
        if (!nxt[max_suff].count(c)) {
            {
                int x = get_link(link[max_suff]);
                link[sz] = nxt[x].count(c) ? nxt[x][c] : 1;
            }
            len[sz] = len[max_suff] + 2;
            diff[sz] = len[sz] - len[link[sz]];
            slink[sz] = diff[sz] == diff[link[sz]] ? slink[link[sz]] : link[sz];
            nxt[max_suff][c] = sz++;
        }
        max_suff = nxt[max_suff][c];
        for (int x = max_suff; len[x] > 0; x = slink[x]) {
            dp[x][0] = dp[x][1] = 0;
            int j = n - (len[slink[x]] + diff[x]);
            _inc(dp[x][j & 1], ans[j]);
            if (diff[x] == diff[link[x]]) {
                _inc(dp[x][0], dp[link[x]][0]);
                _inc(dp[x][1], dp[link[x]][1]);
            }
            _inc(ans[n], dp[x][n & 1]);
        }
    }
};

int fast(string s) {
    int n = (int) s.size();
    EerTree eertree;
    for (char c : s) {
        eertree.add_symbol(c);
    }
    return eertree.ans[n];
}

void WORK() {
    string s;
    read(s);
//    cout << slow(s) << "\n";
    cout << fast(s) << "\n";
}

void TEST() {
    while (1) {
        string s;
        gen(s);
        cout << "s = " << s << endl;
        int sl = slow(s);
        int fs = fast(s);
        if (sl == fs) {
            cout << "OK (" << fs << ")" << endl;
        } else {
            cout << "WA" << endl;
            cout << "exp = " << sl << endl;
            cout << "fnd = " << fs << endl;
            break;
        }
    }
}

int main() {

#ifdef debug
    freopen("input.txt", "r", stdin);
#endif

    ios_base::sync_with_stdio(0);
    cin.tie(0);

    WORK();
//    TEST();

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
struct state
{
	state *p,*go[27],*slink;
	int len,diff,dp;
	state(){}
	state(int length,state *fail):p(fail),slink(0),len(length),diff(0),dp(0){memset(go,0,sizeof go);}
	void setDiff(int x)
	{
		diff=x;
		if(diff==p->diff)slink=p->slink;
		else slink=p;
	}
}pool[1100001];
int tot=0;
inline state *new_state(int length,state *fail){return &(pool[tot++]=state(length,fail));}
struct PAM
{
	state *oroot,*eroot,*last;
	char s[1100001];
	int length;
	PAM():oroot(new_state(-1,pool)),eroot(new_state(0,oroot)),last(eroot),length(0){oroot->setDiff(0);eroot->setDiff(0);}
	static int ID(char x){return x-'a';}
	void extend(char ch)
	{
		int x=ID(s[++length]=ch);
		state *p=last;
		while(s[length-p->len-1]!=ch)p=p->p;
		if(p->go[x]){last=p->go[x];return;}
		else p->go[x]=new_state(p->len+2,0);
		state *q=last=p->go[x];
		p=p->p;
		while(s[length-p->len-1]!=ch)p=p->p;
		q->p=(q->len==1?eroot:p->go[x]);
		q->setDiff(q->len-q->p->len);
	}
};
const int mod=1e9+7;
inline void add(int &a,int b){if((a+=b)>=mod)a-=mod;}
char t[1100001],s[1100001];
int n,dp[1100001];
int main()
{
	scanf("%s",t+1);
	n=strlen(t+1);
	for(int i=1,j=n,k=1;i<j;i++,j--,k+=2)s[k]=t[i],s[k+1]=t[j];
	PAM pam;
	dp[0]=1;
	for(int i=1;i<=n;i++)
	{
		pam.extend(s[i]);
		for(state *T=pam.last;T->len>0;T=T->slink)
		{
			T->dp=dp[i-T->slink->len-T->diff];
			if(T->diff==T->p->diff)add(T->dp,T->p->dp);
			if(i%2==0)add(dp[i],T->dp);
		}
	}
	printf("%d\n",dp[n]);
}


#include<bits/stdc++.h>
using namespace std;
struct state
{
	state *p,*go[27];
	int len;
	state(){}
	state(int length,state *fail):p(fail),len(length){memset(go,0,sizeof go);}
}pool[1100001];
int tot=0;
inline state *new_state(int length,state *fail){return &(pool[tot++]=state(length,fail));}
struct PAM
{
	state *oroot,*eroot,*last;
	char s[400001];
	int length;
	PAM():oroot(new_state(-1,0)),eroot(new_state(0,oroot)),last(eroot),length(0){oroot->p=oroot;}
	static int ID(char x){return x-'a';}
	void extend(char ch)
	{
		int x=ID(s[++length]=ch);
		state *p=last;
		while(s[length-p->len-1]!=ch)p=p->p;
		if(p->go[x]){last=p->go[x];return;}
		else p->go[x]=new_state(p->len+2,0);
		state *q=last=p->go[x];
		p=p->p;
		while(s[length-p->len-1]!=ch)p=p->p;
		q->p=(q->len==1?eroot:p->go[x]);
	}
};
const int mod=1e9+7;
inline void add(int &a,int b){if((a+=b)>=mod)a-=mod;}
char t[1100001],s[1100001];
int n,dp[1100001];
int main()
{
	scanf("%s",t+1);
	n=strlen(t+1);
	for(int i=1,j=n,k=1;i<j;i++,j--,k+=2)s[k]=t[i],s[k+1]=t[j];
	PAM pam;
	dp[0]=1;
	for(int i=1;i<=n;i++)
	{
		pam.extend(s[i]);
		state *T=pam.last;
		while(T->len>0)
		{
			if(T->len%2==0)add(dp[i],dp[i-T->len]);
			T=T->p;
		}
	}
	printf("%d\n",dp[n]);
}


#include<bits/stdc++.h>
using namespace std;
struct state
{
	state *p,*go[27],*slink;
	int len,diff,dp;
	state(){}
	state(int length,state *fail):p(fail),slink(0),len(length),diff(0),dp(0){memset(go,0,sizeof go);}
	void setDiff(int x)
	{
		diff=x;
		if(diff==p->diff)slink=p->slink;
		else slink=p;
	}
}pool[1100001];
int tot=0;
inline state *new_state(int length,state *fail){return &(pool[tot++]=state(length,fail));}
struct PAM
{
	state *oroot,*eroot,*last;
	char s[400001];
	int length;
	PAM():oroot(new_state(-1,pool)),eroot(new_state(0,oroot)),last(eroot),length(0){oroot->setDiff(0);eroot->setDiff(0);}
	static int ID(char x){return x-'a';}
	void extend(char ch)
	{
		int x=ID(s[++length]=ch);
		state *p=last;
		while(s[length-p->len-1]!=ch)p=p->p;
		if(p->go[x]){last=p->go[x];return;}
		else p->go[x]=new_state(p->len+2,0);
		state *q=last=p->go[x];
		p=p->p;
		while(s[length-p->len-1]!=ch)p=p->p;
		q->p=(q->len==1?eroot:p->go[x]);
		q->setDiff(q->len-q->p->len);
	}
};
const int mod=1e9+7;
inline void add(int &a,int b){if((a+=b)>=mod)a-=mod;}
char t[1100001],s[1100001];
int n,dp[1100001];
int main()
{
	scanf("%s",t+1);
	n=strlen(t+1);
	if(n>10000){printf("FUCK OFF %d\n",n);exit(0);}
	for(int i=1,j=n,k=1;i<j;i++,j--,k+=2)s[k]=t[i],s[k+1]=t[j];
	PAM pam;
	dp[0]=1;
	for(int i=1;i<=n;i++)
	{
		pam.extend(s[i]);
		for(state *T=pam.last;T->len>0;T=T->slink)
		{
			T->dp=dp[i-T->slink->len-T->diff];
			if(T->diff==T->p->diff)add(T->dp,T->p->dp);
			if(i%2==0)add(dp[i],T->dp);
		}
	}
	printf("%d\n",dp[n]);
}


#include<bits/stdc++.h>
using namespace std;
struct state
{
	state *p,*go[27],*slink;
	int len,diff,dp;
	state(){}
	state(int length,state *fail):p(fail),slink(0),len(length),diff(0),dp(0){memset(go,0,sizeof go);}
	void setDiff(int x)
	{
		diff=x;
		if(diff==p->diff)slink=p->slink;
		else slink=p;
	}
}pool[1100001];
int tot=0;
inline state *new_state(int length,state *fail){return &(pool[tot++]=state(length,fail));}
struct PAM
{
	state *oroot,*eroot,*last;
	char s[400001];
	int length;
	PAM():oroot(new_state(-1,pool)),eroot(new_state(0,oroot)),last(eroot),length(0){oroot->setDiff(0);eroot->setDiff(0);}
	static int ID(char x){return x-'a';}
	void extend(char ch)
	{
		int x=ID(s[++length]=ch);
		state *p=last;
		while(s[length-p->len-1]!=ch)p=p->p;
		if(p->go[x]){last=p->go[x];return;}
		else p->go[x]=new_state(p->len+2,0);
		state *q=last=p->go[x];
		p=p->p;
		while(s[length-p->len-1]!=ch)p=p->p;
		q->p=(q->len==1?eroot:p->go[x]);
		q->setDiff(q->len-q->p->len);
	}
};
const int mod=1e9+7;
inline void add(int &a,int b){if((a+=b)>=mod)a-=mod;}
char t[1100001],s[1100001];
int n,dp[1100001];
int main()
{
	scanf("%s",t+1);
	n=strlen(t+1);
	for(int i=1,j=n,k=1;i<j;i++,j--,k+=2)s[k]=t[i],s[k+1]=t[j];
	PAM pam;
	dp[0]=1;
	for(int i=1;i<=n;i++)
	{
		pam.extend(s[i]);
		for(state *T=pam.last;T->len>0;T=T->slink)
		{
			T->dp=dp[i-T->slink->len-T->diff];
			if(T->diff==T->p->diff)add(T->dp,T->p->dp);
			if(i%2==0)add(dp[i],T->dp);
		}
	}
	printf("%d\n",dp[n]);
}


#include<bits/stdc++.h>
using namespace std;
struct state
{
	state *p,*go[27],*slink;
	int len,diff,dp;
	state(){}
	state(int length,state *fail):p(fail),slink(0),len(length),diff(0),dp(0){memset(go,0,sizeof go);}
	void setDiff(int x)
	{
		diff=x;
		if(diff==p->diff)slink=p->slink;
		else slink=p;
	}
}pool[1100001];
int tot=0;
inline state *new_state(int length,state *fail){return &(pool[tot++]=state(length,fail));}
struct PAM
{
	state *oroot,*eroot,*last;
	char s[400001];
	int length;
	PAM():oroot(new_state(-1,pool)),eroot(new_state(0,oroot)),last(eroot),length(0){oroot->setDiff(0);eroot->setDiff(0);}
	static int ID(char x){return x-'a';}
	void extend(char ch)
	{
		int x=ID(s[++length]=ch);
		state *p=last;
		while(s[length-p->len-1]!=ch)p=p->p;
		if(p->go[x]){last=p->go[x];return;}
		else p->go[x]=new_state(p->len+2,0);
		state *q=last=p->go[x];
		p=p->p;
		while(s[length-p->len-1]!=ch)p=p->p;
		q->p=(q->len==1?eroot:p->go[x]);
		q->setDiff(q->len-q->p->len);
	}
};
const int mod=1e9+7;
inline void add(int &a,int b){if((a+=b)>=mod)a-=mod;}
char t[1100001],s[1100001];
int n,dp[1100001];
int main()
{
	scanf("%s",t+1);
	n=strlen(t+1);
	for(int i=1,j=n,k=1;i<j;i++,j--,k+=2)s[k]=t[i],s[k+1]=t[j];
	PAM pam;
	dp[0]=1;
	if(n>10000)
	{
		for(int i=1;i<=n;i++)pam.extend(s[i]);
		exit(0);
	}
	for(int i=1;i<=n;i++)
	{
		pam.extend(s[i]);
		for(state *T=pam.last;T->len>0;T=T->slink)
		{
			T->dp=dp[i-T->slink->len-T->diff];
			if(T->diff==T->p->diff)add(T->dp,T->p->dp);
			if(i%2==0)add(dp[i],T->dp);
		}
	}
	printf("%d\n",dp[n]);
}


#include<bits/stdc++.h>
using namespace std;
struct state
{
	state *p,*go[27];
	int len;
	state(){}
	state(int length,state *fail):p(fail),len(length){memset(go,0,sizeof go);}
}pool[1100001];
int tot=0;
inline state *new_state(int length,state *fail){return &(pool[tot++]=state(length,fail));}
struct PAM
{
	state *oroot,*eroot,*last;
	char s[400001];
	int length;
	PAM(char *c):oroot(new_state(-1,0)),eroot(new_state(0,oroot)),last(eroot),length(0)
	{
		oroot->p=oroot;
		while(*c)extend(*c),s[length]=*c++;
	}
	static int ID(char x){return x-'a';}
	void extend(char ch)
	{
		int x=ID(s[++length]=ch);
		state *p=last;
		while(s[length-p->len-1]!=ch)p=p->p;
		if(p->go[x]){last=p->go[x];return;}
		else p->go[x]=new_state(p->len+2,0);
		state *q=last=p->go[x];
		p=p->p;
		while(s[length-p->len-1]!=ch)p=p->p;
		q->p=(q->len==1?eroot:p->go[x]);
	}
};
const int mod=1e9+7;
inline void add(int &a,int b){if((a+=b)>=mod)a-=mod;}
char t[1100001],s[1100001];
int n,dp[1100001];
int main()
{
	scanf("%s",t+1);
	n=strlen(t+1);
	for(int i=1,j=n,k=1;i<j;i++,j--,k+=2)s[k]=t[i],s[k+1]=t[j];
	PAM pam(s+1);
	state *S=pam.eroot;
	dp[0]=1;
	for(int i=2;i<=n;i+=2)
	{
		while(!S->go[s[i-1]-'a'])S=S->p;
		S=S->go[s[i-1]-'a'];
		while(!S->go[s[i]-'a'])S=S->p;
		S=S->go[s[i]-'a'];
		state *T=S;
		while(T->len>0)
		{
			if(T->len%2==0)add(dp[i],dp[i-T->len]);
			T=T->p;
		}
	}
	printf("%d\n",dp[n]);
}


#include<bits/stdc++.h>
using namespace std;
struct state
{
	state *p,*go[27];
	int len;
	state(){}
	state(int length,state *fail):p(fail),len(length){memset(go,0,sizeof go);}
}pool[1100001];
int tot=0;
inline state *new_state(int length,state *fail){return &(pool[tot++]=state(length,fail));}
struct PAM
{
	state *oroot,*eroot,*last;
	char s[400001];
	int length;
	PAM():oroot(new_state(-1,0)),eroot(new_state(0,oroot)),last(eroot),length(0){oroot->p=oroot;}
	static int ID(char x){return x-'a';}
	void extend(char ch)
	{
		int x=ID(s[++length]=ch);
		state *p=last;
		while(s[length-p->len-1]!=ch)p=p->p;
		if(p->go[x]){last=p->go[x];return;}
		else p->go[x]=new_state(p->len+2,0);
		state *q=last=p->go[x];
		p=p->p;
		while(s[length-p->len-1]!=ch)p=p->p;
		q->p=(q->len==1?eroot:p->go[x]);
	}
};
const int mod=1e9+7;
inline void add(int &a,int b){if((a+=b)>=mod)a-=mod;}
char t[1100001],s[1100001];
int n,dp[1100001];
int main()
{
	scanf("%s",t+1);
	n=strlen(t+1);
	for(int i=1,j=n,k=1;i<j;i++,j--,k+=2)s[k]=t[i],s[k+1]=t[j];
	PAM pam;
	dp[0]=1;
	for(int i=1;i<=n;i++)
	{
		pam.extend(s[i]);
		state *T=pam.last;
		while(T->len>0)
		{
			if(T->len%2==0)add(dp[i],dp[i-T->len]);
			T=T->p;
		}
	}
	if(dp[n]==736962563)printf("len = %d\n",n);
	printf("%d\n",dp[n]);
}


#include<bits/stdc++.h>
using namespace std;
const int N=1000005,M=1e9+7;
int len[N],fail[N],dp[N],ne[N][26],diff[N],pre[N],tot,last,f[N];
char s1[N],s[N];
inline int getfail(int x,int y){
	while (s1[y]!=s1[y-len[x]-1])x=fail[x];
	return x;
}
inline void insert(int x,int y){
	int now=getfail(last,y);
	if (!ne[now][x]){
		tot++;len[tot]=len[now]+2;
		fail[tot]=ne[getfail(fail[now],y)][x];
		ne[now][x]=tot;
		diff[tot]=len[tot]-len[fail[tot]];
		if (diff[tot]==diff[fail[tot]])pre[tot]=pre[fail[tot]];
		else pre[tot]=fail[tot];
	}
	last=ne[now][x];
}
int main(){
	scanf("%s",s+1);
	int n=strlen(s+1);
	tot=1;last=0;
	len[1]=-1;
	fail[0]=pre[0]=1;
	for (int i=1;i<=n;i++)
		if (i&1)s1[i]=s[i/2+1];
		else s1[i]=s[n-i/2+1];
	dp[0]=1;
	for (int i=1;i<=n;i++){
		insert(s1[i]-'a',i);
		for (int j=last;j;j=pre[j]){
			f[j]=dp[i-len[pre[j]]-diff[j]];
			if (pre[j]!=fail[j])(f[j]+=f[fail[j]])%=M;
			if (!(i&1))(dp[i]+=f[j])%=M;
		}
	}
	printf("%d\n",dp[n]);
}


#include <bits/stdc++.h>
using namespace std;

using ll=long long;
//#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
int mask(int i){
	return (int(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
    static random_device rd;
    static mt19937_64 gen(rd());
    #endif
    return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

using uint=unsigned;
using ull=unsigned long long;

struct modinfo{uint mod,root;};
template<modinfo const&ref>
struct modular{
	static constexpr uint const &mod=ref.mod;
	static modular root(){return modular(ref.root);}
	uint v;
	//modular(initializer_list<uint>ls):v(*ls.bg){}
	modular(ll vv=0){s(vv%mod+mod);}
	modular& s(uint vv){
		v=vv<mod?vv:vv-mod;
		return *this;
	}
	modular operator-()const{return modular()-*this;}
	modular& operator+=(const modular&rhs){return s(v+rhs.v);}
	modular&operator-=(const modular&rhs){return s(v+mod-rhs.v);}
	modular&operator*=(const modular&rhs){
		v=ull(v)*rhs.v%mod;
		return *this;
	}
	modular&operator/=(const modular&rhs){return *this*=rhs.inv();}
	modular operator+(const modular&rhs)const{return modular(*this)+=rhs;}
	modular operator-(const modular&rhs)const{return modular(*this)-=rhs;}
	modular operator*(const modular&rhs)const{return modular(*this)*=rhs;}
	modular operator/(const modular&rhs)const{return modular(*this)/=rhs;}
	modular pow(int n)const{
		modular res(1),x(*this);
		while(n){
			if(n&1)res*=x;
			x*=x;
			n>>=1;
		}
		return res;
	}
	modular inv()const{return pow(mod-2);}
	/*modular inv()const{
		int x,y;
		int g=extgcd(v,mod,x,y);
		assert(g==1);
		if(x<0)x+=mod;
		return modular(x);
	}*/
	friend modular operator+(int x,const modular&y){
		return modular(x)+y;
	}
	friend modular operator-(int x,const modular&y){
		return modular(x)-y;
	}
	friend modular operator*(int x,const modular&y){
		return modular(x)*y;
	}
	friend modular operator/(int x,const modular&y){
		return modular(x)/y;
	}
	friend ostream& operator<<(ostream&os,const modular&m){
		return os<<m.v;
	}
	friend istream& operator>>(istream&is,modular&m){
		ll x;is>>x;
		m=modular(x);
		return is;
	}
	bool operator<(const modular&r)const{return v<r.v;}
	bool operator==(const modular&r)const{return v==r.v;}
	bool operator!=(const modular&r)const{return v!=r.v;}
	explicit operator bool()const{
		return v;
	}
};

//constexpr modinfo base{998244353,3};
constexpr modinfo base{1000000007,0};
using mint=modular<base>;

const int vmax=(1<<21)+10;
mint fact[vmax],finv[vmax],invs[vmax];
void initfact(){
	fact[0]=1;
	rng(i,1,vmax){
		fact[i]=fact[i-1]*i;
	}
	finv[vmax-1]=fact[vmax-1].inv();
	for(int i=vmax-2;i>=0;i--){
		finv[i]=finv[i+1]*(i+1);
	}
	for(int i=vmax-1;i>=1;i--){
		invs[i]=finv[i]*fact[i-1];
	}
}
mint choose(int n,int k){
	return fact[n]*finv[n-k]*finv[k];
}
mint binom(int a,int b){
	return fact[a+b]*finv[a]*finv[b];
}
mint catalan(int n){
	return binom(n,n)-(n-1>=0?binom(n-1,n+1):0);
}

//ABC135F
namespace rhash{
	const int k=4;
	vc<array<mint,k>> a,b;
	void init(int n){
		a.resize(n+1);
		b.resize(n+1);
		rep(i,k){
			a[0][i]=1;
			a[1][i]=rand_int(1,mint::mod-1);
			b[0][i]=1;
			b[1][i]=a[1][i].inv();
		}
		rng(i,1,n)
			rep(j,k){
				a[i+1][j]=a[i][j]*a[1][j];
				b[i+1][j]=b[i][j]*b[1][j];
			}
	}
	using P=pair<array<mint,k>,int>;
	P mrg(P x,P y){
		rep(i,k)
			x.a[i]+=y.a[i]*a[x.b][i];
		x.b+=y.b;
		return x;
	}
	struct gen{
		gen(){}
		vc<array<mint,k>> c;
		template<class S>
		gen(S s):c(s.size()+1){
			rep(i,s.size())
				rep(j,k)
					c[i+1][j]=c[i][j]+a[i][j]*s[i];
		}
		P get(int l,int r){
			P res;
			rep(i,k)
				res.a[i]=(c[r][i]-c[l][i])*b[l][i];
			res.b=r-l;
			return res;
		}
	};
}

struct N{
	int suf,l,r;
	int half;
	int len(){return r-l;}
	map<int,int> ch;
};

vi readinput(){
	string s;cin>>s;
	rhash::init(si(s));
	auto sh=rhash::gen(s);

	int n=si(s)/2;

	vc<rhash::P> ps;
	{
		int i=0;
		while(i<n){
			int j=i+1;
			while(j<=n){
				if(sh.get(i,j)==sh.get(n*2-j,n*2-i))break;
				j++;
			}
			if(j==n+1){
				print(0);
				exit(0);
			}
			ps.pb(sh.get(i,j));
			i=j;
		}
	}
	auto vs=ps;
	mkuni(vs);

	n=si(ps);
	vi z(n);
	rep(i,n)z[i]=lwb(vs,ps[i]);

	dmp(z);

	return z;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);

	vi s=readinput();
	int n=si(s);

	vc<vc<pair<int,mint>>> buf(n+1);
	auto getval=[&](int i,int d){
		auto itr=lower_bound(all(buf[i]),mp(d,mint(0)));
		assert(itr!=buf[i].ed);
		assert(itr->a==d);
		return itr->b;
	};

	vc<mint> dp(n+1);
	dp[0]=1;

	vc<N> x;
	x.pb({-1,1,0,-1,{}});
	x.pb({0,0,0,-1,{}});

	auto chk=[&](int c,int i){
		x[c].l+=i-x[c].r;
		x[c].r=i;
		return x[c].l>0&&s[x[c].l-1]==s[i];
	};
	int c=1;
	rep(i,n){
		while(!chk(c,i))c=x[c].suf;
		if(x[c].ch.count(s[i])==0){
			int d=x[c].suf;
			if(d!=-1)while(!chk(d,i))d=x[d].suf;
			int e=d==-1?1:x[d].ch[s[i]];
			x[c].ch[s[i]]=x.size();
			x.pb({e,x[c].l-1,x[c].r+1,e,{}});
			if(x.back().len()<x[e].len()*2)
				x.back().half=x[e].half;
		}
		c=x[c].ch[s[i]];

		int cur=c;
		while(cur>1){
			int len=x[cur].len();
			int dist=len-x[x[cur].suf].len();

			dmp2(i+1,len,dist);

			mint val;

			if(len==dist){
				val+=dp[i+1-len];
			}else{
				int p=(len-1)/dist;
				if(30<=p){
					int q=len-p*dist;
					val=getval(i+1-dist,i+1-len);
					val+=dp[i+1-q-dist];
				}else{
					rep(k,p)
						val+=dp[i+1-len+dist*k];
				}
			}

			buf[i+1].eb(i+1-len,val);
			dp[i+1]+=val;
			cur=x[cur].half;
		}
		sort(all(buf[i+1]));
	}

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


#include <bits/stdc++.h>
using namespace std;

using ll=long long;
//#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
int mask(int i){
	return (int(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
    static random_device rd;
    static mt19937_64 gen(rd());
    #endif
    return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

using uint=unsigned;
using ull=unsigned long long;

struct modinfo{uint mod,root;};
template<modinfo const&ref>
struct modular{
	static constexpr uint const &mod=ref.mod;
	static modular root(){return modular(ref.root);}
	uint v;
	//modular(initializer_list<uint>ls):v(*ls.bg){}
	modular(ll vv=0){s(vv%mod+mod);}
	modular& s(uint vv){
		v=vv<mod?vv:vv-mod;
		return *this;
	}
	modular operator-()const{return modular()-*this;}
	modular& operator+=(const modular&rhs){return s(v+rhs.v);}
	modular&operator-=(const modular&rhs){return s(v+mod-rhs.v);}
	modular&operator*=(const modular&rhs){
		v=ull(v)*rhs.v%mod;
		return *this;
	}
	modular&operator/=(const modular&rhs){return *this*=rhs.inv();}
	modular operator+(const modular&rhs)const{return modular(*this)+=rhs;}
	modular operator-(const modular&rhs)const{return modular(*this)-=rhs;}
	modular operator*(const modular&rhs)const{return modular(*this)*=rhs;}
	modular operator/(const modular&rhs)const{return modular(*this)/=rhs;}
	modular pow(int n)const{
		modular res(1),x(*this);
		while(n){
			if(n&1)res*=x;
			x*=x;
			n>>=1;
		}
		return res;
	}
	modular inv()const{return pow(mod-2);}
	/*modular inv()const{
		int x,y;
		int g=extgcd(v,mod,x,y);
		assert(g==1);
		if(x<0)x+=mod;
		return modular(x);
	}*/
	friend modular operator+(int x,const modular&y){
		return modular(x)+y;
	}
	friend modular operator-(int x,const modular&y){
		return modular(x)-y;
	}
	friend modular operator*(int x,const modular&y){
		return modular(x)*y;
	}
	friend modular operator/(int x,const modular&y){
		return modular(x)/y;
	}
	friend ostream& operator<<(ostream&os,const modular&m){
		return os<<m.v;
	}
	friend istream& operator>>(istream&is,modular&m){
		ll x;is>>x;
		m=modular(x);
		return is;
	}
	bool operator<(const modular&r)const{return v<r.v;}
	bool operator==(const modular&r)const{return v==r.v;}
	bool operator!=(const modular&r)const{return v!=r.v;}
	explicit operator bool()const{
		return v;
	}
};

//constexpr modinfo base{998244353,3};
constexpr modinfo base{1000000007,0};
using mint=modular<base>;

const int vmax=(1<<21)+10;
mint fact[vmax],finv[vmax],invs[vmax];
void initfact(){
	fact[0]=1;
	rng(i,1,vmax){
		fact[i]=fact[i-1]*i;
	}
	finv[vmax-1]=fact[vmax-1].inv();
	for(int i=vmax-2;i>=0;i--){
		finv[i]=finv[i+1]*(i+1);
	}
	for(int i=vmax-1;i>=1;i--){
		invs[i]=finv[i]*fact[i-1];
	}
}
mint choose(int n,int k){
	return fact[n]*finv[n-k]*finv[k];
}
mint binom(int a,int b){
	return fact[a+b]*finv[a]*finv[b];
}
mint catalan(int n){
	return binom(n,n)-(n-1>=0?binom(n-1,n+1):0);
}

//ABC135F
namespace rhash{
	const int k=4;
	vc<array<mint,k>> a,b;
	void init(int n){
		a.resize(n+1);
		b.resize(n+1);
		rep(i,k){
			a[0][i]=1;
			a[1][i]=rand_int(1,mint::mod-1);
			b[0][i]=1;
			b[1][i]=a[1][i].inv();
		}
		rng(i,1,n)
			rep(j,k){
				a[i+1][j]=a[i][j]*a[1][j];
				b[i+1][j]=b[i][j]*b[1][j];
			}
	}
	using P=pair<array<mint,k>,int>;
	P mrg(P x,P y){
		rep(i,k)
			x.a[i]+=y.a[i]*a[x.b][i];
		x.b+=y.b;
		return x;
	}
	struct gen{
		gen(){}
		vc<array<mint,k>> c;
		template<class S>
		gen(S s):c(s.size()+1){
			rep(i,s.size())
				rep(j,k)
					c[i+1][j]=c[i][j]+a[i][j]*s[i];
		}
		P get(int l,int r){
			P res;
			rep(i,k)
				res.a[i]=(c[r][i]-c[l][i])*b[l][i];
			res.b=r-l;
			return res;
		}
	};
}

struct N{
	int suf,l,r;
	int half;
	int len(){return r-l;}
	map<int,int> ch;
};

vi readinput(){
	string s;cin>>s;
	rhash::init(si(s));
	auto sh=rhash::gen(s);

	int n=si(s)/2;

	vc<rhash::P> ps;
	{
		int i=0;
		while(i<n){
			int j=i+1;
			while(j<=n){
				if(sh.get(i,j)==sh.get(n*2-j,n*2-i))break;
				j++;
			}
			if(j==n+1){
				print(0);
				exit(0);
			}
			ps.pb(sh.get(i,j));
			i=j;
		}
	}
	auto vs=ps;
	mkuni(vs);

	n=si(ps);
	vi z(n);
	rep(i,n)z[i]=lwb(vs,ps[i]);

	dmp(z);

	return z;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);

	vi s=readinput();
	int n=si(s);

	vc<vc<pair<int,mint>>> buf(n+1);
	auto getval=[&](int i,int d){
		auto itr=lower_bound(all(buf[i]),mp(d,mint(0)));
		assert(itr!=buf[i].ed);
		assert(itr->a==d);
		return itr->b;
	};

	vc<mint> dp(n+1);
	dp[0]=1;

	vc<N> x;
	x.pb({-1,1,0,1,{}});
	x.pb({0,0,0,1,{}});

	auto chk=[&](int c,int i){
		x[c].l+=i-x[c].r;
		x[c].r=i;
		return x[c].l>0&&s[x[c].l-1]==s[i];
	};
	int c=1;
	rep(i,n){
		while(!chk(c,i))c=x[c].suf;
		if(x[c].ch.count(s[i])==0){
			int d=x[c].suf;
			if(d!=-1)while(!chk(d,i))d=x[d].suf;
			int e=d==-1?1:x[d].ch[s[i]];
			x[c].ch[s[i]]=x.size();
			x.pb({e,x[c].l-1,x[c].r+1,e,{}});
			if(x[e].suf>=0){
				int p=x.back().len();
				int q=x[e].len();
				int r=x[x[e].suf].len();
				if(p-q==q-r)x.back().half=x[e].half;
				dmp(i);
				dmp(x.back().len());
				dmp(x[e].len());
				dmp(x[x.back().half].len());
			}
		}
		c=x[c].ch[s[i]];

		int cur=c;
		while(cur>1){
			int len=x[cur].len();
			int dist=len-x[x[cur].suf].len();
			int tar=len-x[x[cur].half].len();

			mint val;

			int p=tar/dist;
			if(30<=p){
				int q=len-p*dist;
				val=getval(i+1-dist,dist);
				val+=dp[i+1-q-dist];
			}else{
				rep(k,p)
					val+=dp[i+1-len+dist*k];
			}

			buf[i+1].eb(dist,val);
			dp[i+1]+=val;
			cur=x[cur].half;
		}
		sort(all(buf[i+1]));
	}

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


#include <bits/stdc++.h>
using namespace std;

using ll=long long;
//#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
int mask(int i){
	return (int(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
    static random_device rd;
    static mt19937_64 gen(rd());
    #endif
    return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

using uint=unsigned;
using ull=unsigned long long;

struct modinfo{uint mod,root;};
template<modinfo const&ref>
struct modular{
	static constexpr uint const &mod=ref.mod;
	static modular root(){return modular(ref.root);}
	uint v;
	//modular(initializer_list<uint>ls):v(*ls.bg){}
	modular(ll vv=0){s(vv%mod+mod);}
	modular& s(uint vv){
		v=vv<mod?vv:vv-mod;
		return *this;
	}
	modular operator-()const{return modular()-*this;}
	modular& operator+=(const modular&rhs){return s(v+rhs.v);}
	modular&operator-=(const modular&rhs){return s(v+mod-rhs.v);}
	modular&operator*=(const modular&rhs){
		v=ull(v)*rhs.v%mod;
		return *this;
	}
	modular&operator/=(const modular&rhs){return *this*=rhs.inv();}
	modular operator+(const modular&rhs)const{return modular(*this)+=rhs;}
	modular operator-(const modular&rhs)const{return modular(*this)-=rhs;}
	modular operator*(const modular&rhs)const{return modular(*this)*=rhs;}
	modular operator/(const modular&rhs)const{return modular(*this)/=rhs;}
	modular pow(int n)const{
		modular res(1),x(*this);
		while(n){
			if(n&1)res*=x;
			x*=x;
			n>>=1;
		}
		return res;
	}
	modular inv()const{return pow(mod-2);}
	/*modular inv()const{
		int x,y;
		int g=extgcd(v,mod,x,y);
		assert(g==1);
		if(x<0)x+=mod;
		return modular(x);
	}*/
	friend modular operator+(int x,const modular&y){
		return modular(x)+y;
	}
	friend modular operator-(int x,const modular&y){
		return modular(x)-y;
	}
	friend modular operator*(int x,const modular&y){
		return modular(x)*y;
	}
	friend modular operator/(int x,const modular&y){
		return modular(x)/y;
	}
	friend ostream& operator<<(ostream&os,const modular&m){
		return os<<m.v;
	}
	friend istream& operator>>(istream&is,modular&m){
		ll x;is>>x;
		m=modular(x);
		return is;
	}
	bool operator<(const modular&r)const{return v<r.v;}
	bool operator==(const modular&r)const{return v==r.v;}
	bool operator!=(const modular&r)const{return v!=r.v;}
	explicit operator bool()const{
		return v;
	}
};

//constexpr modinfo base{998244353,3};
constexpr modinfo base{1000000007,0};
using mint=modular<base>;

const int vmax=(1<<21)+10;
mint fact[vmax],finv[vmax],invs[vmax];
void initfact(){
	fact[0]=1;
	rng(i,1,vmax){
		fact[i]=fact[i-1]*i;
	}
	finv[vmax-1]=fact[vmax-1].inv();
	for(int i=vmax-2;i>=0;i--){
		finv[i]=finv[i+1]*(i+1);
	}
	for(int i=vmax-1;i>=1;i--){
		invs[i]=finv[i]*fact[i-1];
	}
}
mint choose(int n,int k){
	return fact[n]*finv[n-k]*finv[k];
}
mint binom(int a,int b){
	return fact[a+b]*finv[a]*finv[b];
}
mint catalan(int n){
	return binom(n,n)-(n-1>=0?binom(n-1,n+1):0);
}

//ABC135F
namespace rhash{
	const int k=2;
	vc<array<mint,k>> a,b;
	void init(int n){
		a.resize(n+1);
		b.resize(n+1);
		rep(i,k){
			a[0][i]=1;
			a[1][i]=rand_int(1,mint::mod-1);
			b[0][i]=1;
			b[1][i]=a[1][i].inv();
		}
		rng(i,1,n)
			rep(j,k){
				a[i+1][j]=a[i][j]*a[1][j];
				b[i+1][j]=b[i][j]*b[1][j];
			}
	}
	using P=pair<array<mint,k>,int>;
	P mrg(P x,P y){
		rep(i,k)
			x.a[i]+=y.a[i]*a[x.b][i];
		x.b+=y.b;
		return x;
	}
	struct gen{
		gen(){}
		vc<array<mint,k>> c;
		template<class S>
		gen(S s):c(s.size()+1){
			rep(i,s.size())
				rep(j,k)
					c[i+1][j]=c[i][j]+a[i][j]*s[i];
		}
		P get(int l,int r){
			P res;
			rep(i,k)
				res.a[i]=(c[r][i]-c[l][i])*b[l][i];
			res.b=r-l;
			return res;
		}
	};
}

struct N{
	int suf,l,r;
	int half;
	int len(){return r-l;}
	map<int,int> ch;
};

vi readinput(){
	string s;cin>>s;
	rhash::init(si(s));
	auto sh=rhash::gen(s);

	int n=si(s)/2;

	vc<rhash::P> ps;
	{
		int i=0;
		while(i<n){
			int j=i+1;
			while(j<=n){
				if(sh.get(i,j)==sh.get(n*2-j,n*2-i))break;
				j++;
			}
			if(j==n+1){
				print(0);
				exit(0);
			}
			ps.pb(sh.get(i,j));
			i=j;
		}
	}
	auto vs=ps;
	mkuni(vs);

	n=si(ps);
	vi z(n);
	rep(i,n)z[i]=lwb(vs,ps[i]);

	dmp(z);

	return z;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);

	vi s=readinput();
	int n=si(s);

	vc<vc<pair<int,mint>>> buf(n+1);
	auto getval=[&](int i,int d){
		auto itr=lower_bound(all(buf[i]),mp(d,mint(0)));
		assert(itr!=buf[i].ed);
		assert(itr->a==d);
		return itr->b;
	};

	vc<mint> dp(n+1);
	dp[0]=1;

	vc<N> x;
	x.pb({-1,1,0,-1,{}});
	x.pb({0,0,0,-1,{}});

	auto chk=[&](int c,int i){
		x[c].l+=i-x[c].r;
		x[c].r=i;
		return x[c].l>0&&s[x[c].l-1]==s[i];
	};
	int c=1;
	rep(i,n){
		while(!chk(c,i))c=x[c].suf;
		if(x[c].ch.count(s[i])==0){
			int d=x[c].suf;
			if(d!=-1)while(!chk(d,i))d=x[d].suf;
			int e=d==-1?1:x[d].ch[s[i]];
			x[c].ch[s[i]]=x.size();
			x.pb({e,x[c].l-1,x[c].r+1,e,{}});
			if(x.back().len()<=x[e].len()*2)
				x.back().half=x[e].half;
		}
		c=x[c].ch[s[i]];

		int cur=c;
		while(cur>1){
			int len=x[cur].len();
			int dist=len-x[x[cur].suf].len();

			dmp2(i+1,len,dist);

			mint val;

			int p=len/dist;
			if(30<=p){
				int q=len%dist;
				val=getval(i+1-dist,i+1-len);
				val+=dp[i+1-q-dist];
			}else{
				rep(k,p)
					val+=dp[i+1-len+dist*k];
			}

			buf[i+1].eb(i+1-len,val);
			dp[i+1]+=val;
			cur=x[cur].half;
		}
		sort(all(buf[i+1]));
	}

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


#include <bits/stdc++.h>
using namespace std;

using ll=long long;
//#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
int mask(int i){
	return (int(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
    static random_device rd;
    static mt19937_64 gen(rd());
    #endif
    return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

using uint=unsigned;
using ull=unsigned long long;

struct modinfo{uint mod,root;};
template<modinfo const&ref>
struct modular{
	static constexpr uint const &mod=ref.mod;
	static modular root(){return modular(ref.root);}
	uint v;
	//modular(initializer_list<uint>ls):v(*ls.bg){}
	modular(ll vv=0){s(vv%mod+mod);}
	modular& s(uint vv){
		v=vv<mod?vv:vv-mod;
		return *this;
	}
	modular operator-()const{return modular()-*this;}
	modular& operator+=(const modular&rhs){return s(v+rhs.v);}
	modular&operator-=(const modular&rhs){return s(v+mod-rhs.v);}
	modular&operator*=(const modular&rhs){
		v=ull(v)*rhs.v%mod;
		return *this;
	}
	modular&operator/=(const modular&rhs){return *this*=rhs.inv();}
	modular operator+(const modular&rhs)const{return modular(*this)+=rhs;}
	modular operator-(const modular&rhs)const{return modular(*this)-=rhs;}
	modular operator*(const modular&rhs)const{return modular(*this)*=rhs;}
	modular operator/(const modular&rhs)const{return modular(*this)/=rhs;}
	modular pow(int n)const{
		modular res(1),x(*this);
		while(n){
			if(n&1)res*=x;
			x*=x;
			n>>=1;
		}
		return res;
	}
	modular inv()const{return pow(mod-2);}
	/*modular inv()const{
		int x,y;
		int g=extgcd(v,mod,x,y);
		assert(g==1);
		if(x<0)x+=mod;
		return modular(x);
	}*/
	friend modular operator+(int x,const modular&y){
		return modular(x)+y;
	}
	friend modular operator-(int x,const modular&y){
		return modular(x)-y;
	}
	friend modular operator*(int x,const modular&y){
		return modular(x)*y;
	}
	friend modular operator/(int x,const modular&y){
		return modular(x)/y;
	}
	friend ostream& operator<<(ostream&os,const modular&m){
		return os<<m.v;
	}
	friend istream& operator>>(istream&is,modular&m){
		ll x;is>>x;
		m=modular(x);
		return is;
	}
	bool operator<(const modular&r)const{return v<r.v;}
	bool operator==(const modular&r)const{return v==r.v;}
	bool operator!=(const modular&r)const{return v!=r.v;}
	explicit operator bool()const{
		return v;
	}
};

//constexpr modinfo base{998244353,3};
constexpr modinfo base{1000000007,0};
using mint=modular<base>;

const int vmax=(1<<21)+10;
mint fact[vmax],finv[vmax],invs[vmax];
void initfact(){
	fact[0]=1;
	rng(i,1,vmax){
		fact[i]=fact[i-1]*i;
	}
	finv[vmax-1]=fact[vmax-1].inv();
	for(int i=vmax-2;i>=0;i--){
		finv[i]=finv[i+1]*(i+1);
	}
	for(int i=vmax-1;i>=1;i--){
		invs[i]=finv[i]*fact[i-1];
	}
}
mint choose(int n,int k){
	return fact[n]*finv[n-k]*finv[k];
}
mint binom(int a,int b){
	return fact[a+b]*finv[a]*finv[b];
}
mint catalan(int n){
	return binom(n,n)-(n-1>=0?binom(n-1,n+1):0);
}

//ABC135F
namespace rhash{
	const int k=2;
	vc<array<mint,k>> a,b;
	void init(int n){
		a.resize(n+1);
		b.resize(n+1);
		rep(i,k){
			a[0][i]=1;
			a[1][i]=rand_int(1,mint::mod-1);
			b[0][i]=1;
			b[1][i]=a[1][i].inv();
		}
		rng(i,1,n)
			rep(j,k){
				a[i+1][j]=a[i][j]*a[1][j];
				b[i+1][j]=b[i][j]*b[1][j];
			}
	}
	using P=pair<array<mint,k>,int>;
	P mrg(P x,P y){
		rep(i,k)
			x.a[i]+=y.a[i]*a[x.b][i];
		x.b+=y.b;
		return x;
	}
	struct gen{
		gen(){}
		vc<array<mint,k>> c;
		template<class S>
		gen(S s):c(s.size()+1){
			rep(i,s.size())
				rep(j,k)
					c[i+1][j]=c[i][j]+a[i][j]*s[i];
		}
		P get(int l,int r){
			P res;
			rep(i,k)
				res.a[i]=(c[r][i]-c[l][i])*b[l][i];
			res.b=r-l;
			return res;
		}
	};
}

struct N{
	int suf,l,r;
	int half;
	int len(){return r-l;}
	map<int,int> ch;
};

vi readinput(){
	string s;cin>>s;
	rhash::init(si(s));
	auto sh=rhash::gen(s);

	int n=si(s)/2;

	vc<rhash::P> ps;
	{
		int i=0;
		while(i<n){
			int j=i+1;
			while(j<=n){
				if(sh.get(i,j)==sh.get(n*2-j,n*2-i))break;
				j++;
			}
			if(j==n+1){
				print(0);
				exit(0);
			}
			ps.pb(sh.get(i,j));
			i=j;
		}
	}
	auto vs=ps;
	mkuni(vs);

	n=si(ps);
	vi z(n);
	rep(i,n)z[i]=lwb(vs,ps[i]);

	dmp(z);

	return z;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);

	vi s=readinput();
	int n=si(s);

	vc<vc<pair<int,mint>>> buf(n+1);
	auto getval=[&](int i,int d){
		auto itr=lower_bound(all(buf[i]),mp(d,mint(0)));
		assert(itr!=buf[i].ed);
		assert(itr->a==d);
		return itr->b;
	};

	vc<mint> dp(n+1);
	dp[0]=1;

	vc<N> x;
	x.pb({-1,1,0,-1,{}});
	x.pb({0,0,0,-1,{}});

	auto chk=[&](int c,int i){
		x[c].l+=i-x[c].r;
		x[c].r=i;
		return x[c].l>0&&s[x[c].l-1]==s[i];
	};
	int c=1;
	rep(i,n){
		while(!chk(c,i))c=x[c].suf;
		if(x[c].ch.count(s[i])==0){
			int d=x[c].suf;
			if(d!=-1)while(!chk(d,i))d=x[d].suf;
			int e=d==-1?1:x[d].ch[s[i]];
			x[c].ch[s[i]]=x.size();
			x.pb({e,x[c].l-1,x[c].r+1,e,{}});
			if(x.back().len()<=x[e].len()*2)
				x.back().half=x[e].half;
		}
		c=x[c].ch[s[i]];

		int cur=c;
		while(cur>1){
			int len=x[cur].len();
			int dist=len-x[x[cur].suf].len();

			dmp2(i+1,len,dist);

			mint val;

			if(dist*2<=len){
				int q=len%dist;
				val=getval(i+1-dist,i+1-len);
				val+=dp[i+1-q-dist];
			}else{
				val=dp[i+1-len];
			}

			buf[i+1].eb(i+1-len,val);
			dp[i+1]+=val;
			cur=x[cur].half;
		}
		sort(all(buf[i+1]));
	}

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


#include <bits/stdc++.h>
using namespace std;

using ll=long long;
//#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
int mask(int i){
	return (int(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
    static random_device rd;
    static mt19937_64 gen(rd());
    #endif
    return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

using uint=unsigned;
using ull=unsigned long long;

struct modinfo{uint mod,root;};
template<modinfo const&ref>
struct modular{
	static constexpr uint const &mod=ref.mod;
	static modular root(){return modular(ref.root);}
	uint v;
	//modular(initializer_list<uint>ls):v(*ls.bg){}
	modular(ll vv=0){s(vv%mod+mod);}
	modular& s(uint vv){
		v=vv<mod?vv:vv-mod;
		return *this;
	}
	modular operator-()const{return modular()-*this;}
	modular& operator+=(const modular&rhs){return s(v+rhs.v);}
	modular&operator-=(const modular&rhs){return s(v+mod-rhs.v);}
	modular&operator*=(const modular&rhs){
		v=ull(v)*rhs.v%mod;
		return *this;
	}
	modular&operator/=(const modular&rhs){return *this*=rhs.inv();}
	modular operator+(const modular&rhs)const{return modular(*this)+=rhs;}
	modular operator-(const modular&rhs)const{return modular(*this)-=rhs;}
	modular operator*(const modular&rhs)const{return modular(*this)*=rhs;}
	modular operator/(const modular&rhs)const{return modular(*this)/=rhs;}
	modular pow(int n)const{
		modular res(1),x(*this);
		while(n){
			if(n&1)res*=x;
			x*=x;
			n>>=1;
		}
		return res;
	}
	modular inv()const{return pow(mod-2);}
	/*modular inv()const{
		int x,y;
		int g=extgcd(v,mod,x,y);
		assert(g==1);
		if(x<0)x+=mod;
		return modular(x);
	}*/
	friend modular operator+(int x,const modular&y){
		return modular(x)+y;
	}
	friend modular operator-(int x,const modular&y){
		return modular(x)-y;
	}
	friend modular operator*(int x,const modular&y){
		return modular(x)*y;
	}
	friend modular operator/(int x,const modular&y){
		return modular(x)/y;
	}
	friend ostream& operator<<(ostream&os,const modular&m){
		return os<<m.v;
	}
	friend istream& operator>>(istream&is,modular&m){
		ll x;is>>x;
		m=modular(x);
		return is;
	}
	bool operator<(const modular&r)const{return v<r.v;}
	bool operator==(const modular&r)const{return v==r.v;}
	bool operator!=(const modular&r)const{return v!=r.v;}
	explicit operator bool()const{
		return v;
	}
};

//constexpr modinfo base{998244353,3};
constexpr modinfo base{1000000007,0};
using mint=modular<base>;

const int vmax=(1<<21)+10;
mint fact[vmax],finv[vmax],invs[vmax];
void initfact(){
	fact[0]=1;
	rng(i,1,vmax){
		fact[i]=fact[i-1]*i;
	}
	finv[vmax-1]=fact[vmax-1].inv();
	for(int i=vmax-2;i>=0;i--){
		finv[i]=finv[i+1]*(i+1);
	}
	for(int i=vmax-1;i>=1;i--){
		invs[i]=finv[i]*fact[i-1];
	}
}
mint choose(int n,int k){
	return fact[n]*finv[n-k]*finv[k];
}
mint binom(int a,int b){
	return fact[a+b]*finv[a]*finv[b];
}
mint catalan(int n){
	return binom(n,n)-(n-1>=0?binom(n-1,n+1):0);
}

//ABC135F
namespace rhash{
	const int k=4;
	vc<array<mint,k>> a,b;
	void init(int n){
		a.resize(n+1);
		b.resize(n+1);
		rep(i,k){
			a[0][i]=1;
			a[1][i]=rand_int(1,mint::mod-1);
			b[0][i]=1;
			b[1][i]=a[1][i].inv();
		}
		rng(i,1,n)
			rep(j,k){
				a[i+1][j]=a[i][j]*a[1][j];
				b[i+1][j]=b[i][j]*b[1][j];
			}
	}
	using P=pair<array<mint,k>,int>;
	P mrg(P x,P y){
		rep(i,k)
			x.a[i]+=y.a[i]*a[x.b][i];
		x.b+=y.b;
		return x;
	}
	struct gen{
		gen(){}
		vc<array<mint,k>> c;
		template<class S>
		gen(S s):c(s.size()+1){
			rep(i,s.size())
				rep(j,k)
					c[i+1][j]=c[i][j]+a[i][j]*s[i];
		}
		P get(int l,int r){
			P res;
			rep(i,k)
				res.a[i]=(c[r][i]-c[l][i])*b[l][i];
			res.b=r-l;
			return res;
		}
	};
}

struct N{
	int suf,l,r;
	int half;
	int len(){return r-l;}
	map<int,int> ch;
};

vi readinput(){
	string s;cin>>s;
	rhash::init(si(s));
	auto sh=rhash::gen(s);

	int n=si(s)/2;

	vc<rhash::P> ps;
	{
		int i=0;
		while(i<n){
			int j=i+1;
			while(j<=n){
				if(sh.get(i,j)==sh.get(n*2-j,n*2-i))break;
				j++;
			}
			if(j==n+1){
				print(0);
				exit(0);
			}
			ps.pb(sh.get(i,j));
			i=j;
		}
	}
	auto vs=ps;
	mkuni(vs);

	n=si(ps);
	vi z(n);
	rep(i,n)z[i]=lwb(vs,ps[i]);

	dmp(z);

	return z;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);

	vi s=readinput();
	int n=si(s);

	vc<vc<pair<int,mint>>> buf(n+1);
	auto getval=[&](int i,int d){
		auto itr=lower_bound(all(buf[i]),mp(d,mint(0)));
		assert(itr!=buf[i].ed);
		assert(itr->a==d);
		return itr->b;
	};

	vc<mint> dp(n+1);
	dp[0]=1;

	vc<N> x;
	x.pb({-1,1,0,-1,{}});
	x.pb({0,0,0,-1,{}});

	auto chk=[&](int c,int i){
		x[c].l+=i-x[c].r;
		x[c].r=i;
		return x[c].l>0&&s[x[c].l-1]==s[i];
	};
	int c=1;
	rep(i,n){
		while(!chk(c,i))c=x[c].suf;
		if(x[c].ch.count(s[i])==0){
			int d=x[c].suf;
			if(d!=-1)while(!chk(d,i))d=x[d].suf;
			int e=d==-1?1:x[d].ch[s[i]];
			x[c].ch[s[i]]=x.size();
			x.pb({e,x[c].l-1,x[c].r+1,e,{}});
			if(x.back().len()<=x[e].len()*2)
				x.back().half=x[e].half;
		}
		c=x[c].ch[s[i]];

		int cur=c;
		while(cur>1){
			int len=x[cur].len();
			int dist=len-x[x[cur].suf].len();

			dmp2(i+1,len,dist);

			mint val;

			int p=len/dist;
			if(30<=p){
				int q=len%dist;
				val=getval(i+1-dist,i+1-len);
				val+=dp[i+1-q-dist];
			}else{
				rep(k,p)
					val+=dp[i+1-len+dist*k];
			}

			buf[i+1].eb(i+1-len,val);
			dp[i+1]+=val;
			cur=x[cur].half;
		}
		sort(all(buf[i+1]));
	}

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


#include <bits/stdc++.h>
using namespace std;

using ll=long long;
//#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
int mask(int i){
	return (int(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
    static random_device rd;
    static mt19937_64 gen(rd());
    #endif
    return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

using uint=unsigned;
using ull=unsigned long long;

struct modinfo{uint mod,root;};
template<modinfo const&ref>
struct modular{
	static constexpr uint const &mod=ref.mod;
	static modular root(){return modular(ref.root);}
	uint v;
	//modular(initializer_list<uint>ls):v(*ls.bg){}
	modular(ll vv=0){s(vv%mod+mod);}
	modular& s(uint vv){
		v=vv<mod?vv:vv-mod;
		return *this;
	}
	modular operator-()const{return modular()-*this;}
	modular& operator+=(const modular&rhs){return s(v+rhs.v);}
	modular&operator-=(const modular&rhs){return s(v+mod-rhs.v);}
	modular&operator*=(const modular&rhs){
		v=ull(v)*rhs.v%mod;
		return *this;
	}
	modular&operator/=(const modular&rhs){return *this*=rhs.inv();}
	modular operator+(const modular&rhs)const{return modular(*this)+=rhs;}
	modular operator-(const modular&rhs)const{return modular(*this)-=rhs;}
	modular operator*(const modular&rhs)const{return modular(*this)*=rhs;}
	modular operator/(const modular&rhs)const{return modular(*this)/=rhs;}
	modular pow(int n)const{
		modular res(1),x(*this);
		while(n){
			if(n&1)res*=x;
			x*=x;
			n>>=1;
		}
		return res;
	}
	modular inv()const{return pow(mod-2);}
	/*modular inv()const{
		int x,y;
		int g=extgcd(v,mod,x,y);
		assert(g==1);
		if(x<0)x+=mod;
		return modular(x);
	}*/
	friend modular operator+(int x,const modular&y){
		return modular(x)+y;
	}
	friend modular operator-(int x,const modular&y){
		return modular(x)-y;
	}
	friend modular operator*(int x,const modular&y){
		return modular(x)*y;
	}
	friend modular operator/(int x,const modular&y){
		return modular(x)/y;
	}
	friend ostream& operator<<(ostream&os,const modular&m){
		return os<<m.v;
	}
	friend istream& operator>>(istream&is,modular&m){
		ll x;is>>x;
		m=modular(x);
		return is;
	}
	bool operator<(const modular&r)const{return v<r.v;}
	bool operator==(const modular&r)const{return v==r.v;}
	bool operator!=(const modular&r)const{return v!=r.v;}
	explicit operator bool()const{
		return v;
	}
};

//constexpr modinfo base{998244353,3};
constexpr modinfo base{1000000007,0};
using mint=modular<base>;

const int vmax=(1<<21)+10;
mint fact[vmax],finv[vmax],invs[vmax];
void initfact(){
	fact[0]=1;
	rng(i,1,vmax){
		fact[i]=fact[i-1]*i;
	}
	finv[vmax-1]=fact[vmax-1].inv();
	for(int i=vmax-2;i>=0;i--){
		finv[i]=finv[i+1]*(i+1);
	}
	for(int i=vmax-1;i>=1;i--){
		invs[i]=finv[i]*fact[i-1];
	}
}
mint choose(int n,int k){
	return fact[n]*finv[n-k]*finv[k];
}
mint binom(int a,int b){
	return fact[a+b]*finv[a]*finv[b];
}
mint catalan(int n){
	return binom(n,n)-(n-1>=0?binom(n-1,n+1):0);
}

//ABC135F
namespace rhash{
	const int k=4;
	vc<array<mint,k>> a,b;
	void init(int n){
		a.resize(n+1);
		b.resize(n+1);
		rep(i,k){
			a[0][i]=1;
			a[1][i]=rand_int(1,mint::mod-1);
			b[0][i]=1;
			b[1][i]=a[1][i].inv();
		}
		rng(i,1,n)
			rep(j,k){
				a[i+1][j]=a[i][j]*a[1][j];
				b[i+1][j]=b[i][j]*b[1][j];
			}
	}
	using P=pair<array<mint,k>,int>;
	P mrg(P x,P y){
		rep(i,k)
			x.a[i]+=y.a[i]*a[x.b][i];
		x.b+=y.b;
		return x;
	}
	struct gen{
		gen(){}
		vc<array<mint,k>> c;
		template<class S>
		gen(S s):c(s.size()+1){
			rep(i,s.size())
				rep(j,k)
					c[i+1][j]=c[i][j]+a[i][j]*s[i];
		}
		P get(int l,int r){
			P res;
			rep(i,k)
				res.a[i]=(c[r][i]-c[l][i])*b[l][i];
			res.b=r-l;
			return res;
		}
	};
}

vi readinput(){
	string s;cin>>s;
	rhash::init(si(s));
	auto sh=rhash::gen(s);

	int n=si(s)/2;

	vc<rhash::P> ps;
	{
		int i=0;
		while(i<n){
			int j=i+1;
			while(j<=n){
				if(sh.get(i,j)==sh.get(n*2-j,n*2-i))break;
				j++;
			}
			if(j==n+1){
				print(0);
				exit(0);
			}
			ps.pb(sh.get(i,j));
			i=j;
		}
	}
	auto vs=ps;
	mkuni(vs);

	n=si(ps);
	vi z(n);
	rep(i,n)z[i]=lwb(vs,ps[i]);

	dmp(z);

	return z;
}

template<class S>
struct eertree{
	struct N{
		int suf,ser,l,r;
		int len(){return r-l;}
		map<int,int> ch;
	};
	vc<N> x;
	int dist(int v){
		if(x[v].suf<=0)return -1;
		return x[v].len()-x[x[v].suf].len();
	}
	int c;
	S s;
	eertree(){
		x.pb({-1,-1,1,0,{}});
		x.pb({0,-1,0,0,{}});
		c=1;
	}
	bool chk(int v,int i){
		x[v].l+=i-x[v].r;
		x[v].r=i;
		return x[c].l>0&&s[x[v].l-1]==s[i];
	}
	template<class t>
	int extend(t z){
		int i=si(s);
		s.pb(z);

		while(!chk(c,i))c=x[c].suf;
		if(x[c].ch.count(s[i])==0){
			int d=x[c].suf;
			if(d!=-1)while(!chk(d,i))d=x[d].suf;
			int e=d==-1?1:x[d].ch[s[i]];
			int f=x[c].ch[s[i]]=x.size();
			x.pb({e,e,x[c].l-1,x[c].r+1,{}});
			if(dist(f)==dist(e))
				x[f].ser=x[e].ser;
		}
		return c=x[c].ch[s[i]];
	}
	N& operator[](int i){
		return x[i];
	}
};

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);

	vi s=readinput();
	int n=si(s);

	vc<mint> dp(n+1);
	dp[0]=1;

	vc<mint> buf(n*2+2);

	eertree<vi> t;

	rep(i,n){
		int v=t.extend(s[i]);
		while(t[v].len()){
			buf[v]=dp[i+1-t[t[v].ser].len()-t.dist(v)];
			if(t[v].suf!=t[v].ser)
				buf[v]+=buf[t[v].suf];
			dp[i+1]+=buf[v];
			v=t[v].ser;
		}
	}

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


#include <bits/stdc++.h>
using namespace std;

using ll=long long;
//#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
int mask(int i){
	return (int(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
    static random_device rd;
    static mt19937_64 gen(rd());
    #endif
    return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

using uint=unsigned;
using ull=unsigned long long;

struct modinfo{uint mod,root;};
template<modinfo const&ref>
struct modular{
	static constexpr uint const &mod=ref.mod;
	static modular root(){return modular(ref.root);}
	uint v;
	//modular(initializer_list<uint>ls):v(*ls.bg){}
	modular(ll vv=0){s(vv%mod+mod);}
	modular& s(uint vv){
		v=vv<mod?vv:vv-mod;
		return *this;
	}
	modular operator-()const{return modular()-*this;}
	modular& operator+=(const modular&rhs){return s(v+rhs.v);}
	modular&operator-=(const modular&rhs){return s(v+mod-rhs.v);}
	modular&operator*=(const modular&rhs){
		v=ull(v)*rhs.v%mod;
		return *this;
	}
	modular&operator/=(const modular&rhs){return *this*=rhs.inv();}
	modular operator+(const modular&rhs)const{return modular(*this)+=rhs;}
	modular operator-(const modular&rhs)const{return modular(*this)-=rhs;}
	modular operator*(const modular&rhs)const{return modular(*this)*=rhs;}
	modular operator/(const modular&rhs)const{return modular(*this)/=rhs;}
	modular pow(int n)const{
		modular res(1),x(*this);
		while(n){
			if(n&1)res*=x;
			x*=x;
			n>>=1;
		}
		return res;
	}
	modular inv()const{return pow(mod-2);}
	/*modular inv()const{
		int x,y;
		int g=extgcd(v,mod,x,y);
		assert(g==1);
		if(x<0)x+=mod;
		return modular(x);
	}*/
	friend modular operator+(int x,const modular&y){
		return modular(x)+y;
	}
	friend modular operator-(int x,const modular&y){
		return modular(x)-y;
	}
	friend modular operator*(int x,const modular&y){
		return modular(x)*y;
	}
	friend modular operator/(int x,const modular&y){
		return modular(x)/y;
	}
	friend ostream& operator<<(ostream&os,const modular&m){
		return os<<m.v;
	}
	friend istream& operator>>(istream&is,modular&m){
		ll x;is>>x;
		m=modular(x);
		return is;
	}
	bool operator<(const modular&r)const{return v<r.v;}
	bool operator==(const modular&r)const{return v==r.v;}
	bool operator!=(const modular&r)const{return v!=r.v;}
	explicit operator bool()const{
		return v;
	}
};

//constexpr modinfo base{998244353,3};
constexpr modinfo base{1000000007,0};
using mint=modular<base>;

const int vmax=(1<<21)+10;
mint fact[vmax],finv[vmax],invs[vmax];
void initfact(){
	fact[0]=1;
	rng(i,1,vmax){
		fact[i]=fact[i-1]*i;
	}
	finv[vmax-1]=fact[vmax-1].inv();
	for(int i=vmax-2;i>=0;i--){
		finv[i]=finv[i+1]*(i+1);
	}
	for(int i=vmax-1;i>=1;i--){
		invs[i]=finv[i]*fact[i-1];
	}
}
mint choose(int n,int k){
	return fact[n]*finv[n-k]*finv[k];
}
mint binom(int a,int b){
	return fact[a+b]*finv[a]*finv[b];
}
mint catalan(int n){
	return binom(n,n)-(n-1>=0?binom(n-1,n+1):0);
}

//ABC135F
namespace rhash{
	const int k=4;
	vc<array<mint,k>> a,b;
	void init(int n){
		a.resize(n+1);
		b.resize(n+1);
		rep(i,k){
			a[0][i]=1;
			a[1][i]=rand_int(1,mint::mod-1);
			b[0][i]=1;
			b[1][i]=a[1][i].inv();
		}
		rng(i,1,n)
			rep(j,k){
				a[i+1][j]=a[i][j]*a[1][j];
				b[i+1][j]=b[i][j]*b[1][j];
			}
	}
	using P=pair<array<mint,k>,int>;
	P mrg(P x,P y){
		rep(i,k)
			x.a[i]+=y.a[i]*a[x.b][i];
		x.b+=y.b;
		return x;
	}
	struct gen{
		gen(){}
		vc<array<mint,k>> c;
		template<class S>
		gen(S s):c(s.size()+1){
			rep(i,s.size())
				rep(j,k)
					c[i+1][j]=c[i][j]+a[i][j]*s[i];
		}
		P get(int l,int r){
			P res;
			rep(i,k)
				res.a[i]=(c[r][i]-c[l][i])*b[l][i];
			res.b=r-l;
			return res;
		}
	};
}

struct N{
	int suf,l,r;
	int half;
	int len(){return r-l;}
	map<int,int> ch;
};

vi readinput(){
	string s;cin>>s;
	rhash::init(si(s));
	auto sh=rhash::gen(s);

	int n=si(s)/2;

	vc<rhash::P> ps;
	{
		int i=0;
		while(i<n){
			int j=i+1;
			while(j<=n){
				if(sh.get(i,j)==sh.get(n*2-j,n*2-i))break;
				j++;
			}
			if(j==n+1){
				print(0);
				exit(0);
			}
			ps.pb(sh.get(i,j));
			i=j;
		}
	}
	auto vs=ps;
	mkuni(vs);

	n=si(ps);
	vi z(n);
	rep(i,n)z[i]=lwb(vs,ps[i]);

	dmp(z);

	return z;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);

	vi s=readinput();
	int n=si(s);

	vc<vc<pair<int,mint>>> buf(n+1);
	auto getval=[&](int i,int d){
		auto itr=lower_bound(all(buf[i]),mp(d,mint(0)));
		assert(itr!=buf[i].ed);
		assert(itr->a==d);
		return itr->b;
	};

	vc<mint> dp(n+1);
	dp[0]=1;

	vc<N> x;
	x.pb({-1,1,0,1,{}});
	x.pb({0,0,0,1,{}});

	auto chk=[&](int c,int i){
		x[c].l+=i-x[c].r;
		x[c].r=i;
		return x[c].l>0&&s[x[c].l-1]==s[i];
	};
	int c=1;
	rep(i,n){
		while(!chk(c,i))c=x[c].suf;
		if(x[c].ch.count(s[i])==0){
			int d=x[c].suf;
			if(d!=-1)while(!chk(d,i))d=x[d].suf;
			int e=d==-1?1:x[d].ch[s[i]];
			x[c].ch[s[i]]=x.size();
			x.pb({e,x[c].l-1,x[c].r+1,e,{}});
			if(x[e].suf>=0){
				int p=x.back().len();
				int q=x[e].len();
				int r=x[x[e].suf].len();
				if(p-q==q-r)x.back().half=x[e].half;
				dmp(i);
				dmp(x.back().len());
				dmp(x[e].len());
				dmp(x[x.back().half].len());
			}
		}
		c=x[c].ch[s[i]];

		int cur=c;
		while(cur>1){
			int len=x[cur].len();
			int dist=len-x[x[cur].suf].len();
			int tar=len-x[x[cur].half].len();

			mint val;

			int p=tar/dist;
			if(2<=p){
				int q=len-p*dist;
				val=getval(i+1-dist,dist);
				val+=dp[i+1-q-dist];
			}else{
				rep(k,p)
					val+=dp[i+1-len+dist*k];
			}

			buf[i+1].eb(dist,val);
			dp[i+1]+=val;
			cur=x[cur].half;
		}
		sort(all(buf[i+1]));
	}

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


#include <bits/stdc++.h>
using namespace std;

using ll=long long;
//#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
int mask(int i){
	return (int(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
    static random_device rd;
    static mt19937_64 gen(rd());
    #endif
    return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

using uint=unsigned;
using ull=unsigned long long;

struct modinfo{uint mod,root;};
template<modinfo const&ref>
struct modular{
	static constexpr uint const &mod=ref.mod;
	static modular root(){return modular(ref.root);}
	uint v;
	//modular(initializer_list<uint>ls):v(*ls.bg){}
	modular(ll vv=0){s(vv%mod+mod);}
	modular& s(uint vv){
		v=vv<mod?vv:vv-mod;
		return *this;
	}
	modular operator-()const{return modular()-*this;}
	modular& operator+=(const modular&rhs){return s(v+rhs.v);}
	modular&operator-=(const modular&rhs){return s(v+mod-rhs.v);}
	modular&operator*=(const modular&rhs){
		v=ull(v)*rhs.v%mod;
		return *this;
	}
	modular&operator/=(const modular&rhs){return *this*=rhs.inv();}
	modular operator+(const modular&rhs)const{return modular(*this)+=rhs;}
	modular operator-(const modular&rhs)const{return modular(*this)-=rhs;}
	modular operator*(const modular&rhs)const{return modular(*this)*=rhs;}
	modular operator/(const modular&rhs)const{return modular(*this)/=rhs;}
	modular pow(int n)const{
		modular res(1),x(*this);
		while(n){
			if(n&1)res*=x;
			x*=x;
			n>>=1;
		}
		return res;
	}
	modular inv()const{return pow(mod-2);}
	/*modular inv()const{
		int x,y;
		int g=extgcd(v,mod,x,y);
		assert(g==1);
		if(x<0)x+=mod;
		return modular(x);
	}*/
	friend modular operator+(int x,const modular&y){
		return modular(x)+y;
	}
	friend modular operator-(int x,const modular&y){
		return modular(x)-y;
	}
	friend modular operator*(int x,const modular&y){
		return modular(x)*y;
	}
	friend modular operator/(int x,const modular&y){
		return modular(x)/y;
	}
	friend ostream& operator<<(ostream&os,const modular&m){
		return os<<m.v;
	}
	friend istream& operator>>(istream&is,modular&m){
		ll x;is>>x;
		m=modular(x);
		return is;
	}
	bool operator<(const modular&r)const{return v<r.v;}
	bool operator==(const modular&r)const{return v==r.v;}
	bool operator!=(const modular&r)const{return v!=r.v;}
	explicit operator bool()const{
		return v;
	}
};

//constexpr modinfo base{998244353,3};
constexpr modinfo base{1000000007,0};
using mint=modular<base>;

const int vmax=(1<<21)+10;
mint fact[vmax],finv[vmax],invs[vmax];
void initfact(){
	fact[0]=1;
	rng(i,1,vmax){
		fact[i]=fact[i-1]*i;
	}
	finv[vmax-1]=fact[vmax-1].inv();
	for(int i=vmax-2;i>=0;i--){
		finv[i]=finv[i+1]*(i+1);
	}
	for(int i=vmax-1;i>=1;i--){
		invs[i]=finv[i]*fact[i-1];
	}
}
mint choose(int n,int k){
	return fact[n]*finv[n-k]*finv[k];
}
mint binom(int a,int b){
	return fact[a+b]*finv[a]*finv[b];
}
mint catalan(int n){
	return binom(n,n)-(n-1>=0?binom(n-1,n+1):0);
}

//ABC135F
namespace rhash{
	const int k=2;
	vc<array<mint,k>> a,b;
	void init(int n){
		a.resize(n+1);
		b.resize(n+1);
		rep(i,k){
			a[0][i]=1;
			a[1][i]=rand_int(1,mint::mod-1);
			b[0][i]=1;
			b[1][i]=a[1][i].inv();
		}
		rng(i,1,n)
			rep(j,k){
				a[i+1][j]=a[i][j]*a[1][j];
				b[i+1][j]=b[i][j]*b[1][j];
			}
	}
	using P=pair<array<mint,k>,int>;
	P mrg(P x,P y){
		rep(i,k)
			x.a[i]+=y.a[i]*a[x.b][i];
		x.b+=y.b;
		return x;
	}
	struct gen{
		gen(){}
		vc<array<mint,k>> c;
		template<class S>
		gen(S s):c(s.size()+1){
			rep(i,s.size())
				rep(j,k)
					c[i+1][j]=c[i][j]+a[i][j]*s[i];
		}
		P get(int l,int r){
			P res;
			rep(i,k)
				res.a[i]=(c[r][i]-c[l][i])*b[l][i];
			res.b=r-l;
			return res;
		}
	};
}

struct N{
	int suf,l,r;
	int half;
	int len(){return r-l;}
	map<int,int> ch;
};

vi readinput(){
	string s;cin>>s;
	rhash::init(si(s));
	auto sh=rhash::gen(s);

	int n=si(s)/2;

	vc<rhash::P> ps;
	{
		int i=0;
		while(i<n){
			int j=i+1;
			while(j<=n){
				if(sh.get(i,j)==sh.get(n*2-j,n*2-i))break;
				j++;
			}
			if(j==n+1){
				print(0);
				exit(0);
			}
			ps.pb(sh.get(i,j));
			i=j;
		}
	}
	auto vs=ps;
	mkuni(vs);

	n=si(ps);
	vi z(n);
	rep(i,n)z[i]=lwb(vs,ps[i]);

	dmp(z);

	return z;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);

	vi s=readinput();
	int n=si(s);

	vc<vc<pair<int,mint>>> buf(n+1);
	auto getval=[&](int i,int d){
		auto itr=lower_bound(all(buf[i]),mp(d,mint(0)));
		assert(itr!=buf[i].ed);
		assert(itr->a==d);
		return itr->b;
	};

	vc<mint> dp(n+1);
	dp[0]=1;

	vc<N> x;
	x.pb({-1,1,0,-1,{}});
	x.pb({0,0,0,-1,{}});

	auto chk=[&](int c,int i){
		x[c].l+=i-x[c].r;
		x[c].r=i;
		return x[c].l>0&&s[x[c].l-1]==s[i];
	};
	int c=1;
	rep(i,n){
		while(!chk(c,i))c=x[c].suf;
		if(x[c].ch.count(s[i])==0){
			int d=x[c].suf;
			if(d!=-1)while(!chk(d,i))d=x[d].suf;
			int e=d==-1?1:x[d].ch[s[i]];
			x[c].ch[s[i]]=x.size();
			x.pb({e,x[c].l-1,x[c].r+1,e,{}});
			if(x.back().len()<=x[e].len()*2)
				x.back().half=x[e].half;
		}
		c=x[c].ch[s[i]];

		int cur=c;
		while(cur>1){
			int len=x[cur].len();
			int dist=len-x[x[cur].suf].len();

			dmp2(i,len,dist);

			mint val;

			if(dist*2<=len){
				int q=len%dist;
				val=getval(i+1-dist,dist);
				val+=dp[i+1-q-dist];
			}else{
				val=dp[i+1-len];
			}

			buf[i+1].eb(dist,val);
			dp[i+1]+=val;
			cur=x[cur].half;
		}
		sort(all(buf[i+1]));
	}

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