#include<bits/stdc++.h>
using namespace std;
const int NMAX = 1e5 + 10;
const int LOGMAX = 20;
typedef pair<int, int> pii;
typedef long long int ll;
ifstream fin("pscpld.in");
ofstream fout("pscpld.out");
int suffix[NMAX + 1][LOGMAX + 1];
string s;
int n;
struct Triplet {
int index, left, right;
};
bool cmp(const Triplet &a, const Triplet &b) {
if (a.left != b.left)
return a.left < b.left;
return a.right < b.right;
}
void compute_suffix() {
for (int i = 0; i < n; i++)
suffix[i][0] = s[i] - 'a';
for (int j = 1; j <= LOGMAX; j++) {
vector<Triplet> aux;
for (int i = 0; i + (1 << j) - 1 < n; i++) {
aux.push_back({
i,
suffix[i][j - 1],
suffix[i + (1 << (j - 1))][j - 1]
});
}
sort(aux.begin(), aux.end(), cmp);
int rank = 0;
for (int i = 0; i < aux.size(); i++) {
if (i > 0 && (aux[i].left != aux[i - 1].left ||
aux[i].right != aux[i - 1].right)) {
rank++;
}
suffix[aux[i].index][j] = rank;
}
}
}
string mirror(const string &a) {
string result = "";
for (int i = a.size() - 1; i >= 0; i--) {
result += a[i];
}
return result;
}
bool query(pii a, pii b) {
if (a.second - a.first != b.second - b.first)
return false;
int len = a.second - a.first + 1;
int log_query = 31 - __builtin_clz(len);
bool left_son =
suffix[a.first][log_query] ==
suffix[b.first][log_query];
bool right_son =
suffix[a.second - (1 << log_query) + 1][log_query] ==
suffix[b.second - (1 << log_query) + 1][log_query];
return left_son && right_son;
}
int get_odd_palindrome(const int &m, const int center) {
int left = 0;
int right = center;
int current_middle = -1;
while (left <= right) {
int middle = (left + right) / 2;
int string_length = center - middle + 1;
if (center + string_length > m) {
left = middle + 1;
continue;
}
int ans = query({middle, center}, {n - center - string_length, n - center - 1});
//fout << middle << ' ' << center << ' ' << string_length << ' ' << ans <<'\n';
//fout << middle << ' ' << center << ' ' << m - center - string_length << ' ' << m - center - 1 << '\n';
if (ans) {
current_middle = middle;
right = middle - 1;
}
else
left = middle + 1;
// abaddaba
}
return current_middle == -1 ? 0 : (center - current_middle + 1);
}
int get_even_palindrome(const int &m, const int center) {
if (center == m - 1) return 0;
int left = 0;
int right = center;
int current_middle = -1;
while (left <= right) {
int middle = (left + right) / 2;
int string_length = center - middle + 1;
if (center + string_length > m) {
left = middle + 1;
continue;
}
int ans = query({middle, center}, {n - center - string_length - 1, n - center - 2});
//fout << middle << ' ' << center << ' ' << string_length << ' ' << ans <<'\n';
//fout << middle << ' ' << center << ' ' << n - center - string_length - 1 << ' ' << n - center - 2 << '\n';
if (ans) {
current_middle = middle;
right = middle - 1;
}
else
left = middle + 1;
// abaddaba
}
//fout << current_middle << ' ' << center << '\n';
return current_middle == -1 ? 0 : (center - current_middle + 1);
}
int main() {
ios::sync_with_stdio(false);
fin.tie(nullptr);
fout.tie(nullptr);
string original;
fin >> original;
int m = original.size();
string reversed = original;
reverse(reversed.begin(), reversed.end());
s = original + reversed;
n = s.size();
compute_suffix();
ll palindroame = 0;
for (int center = 0; center < m; center++) {
palindroame = palindroame + get_odd_palindrome(m, center) + get_even_palindrome(m, center);
}
fout << palindroame << '\n';
return 0;
}