#include <cstdio>
#include <iostream>
#include <fstream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <string>
#include <ctime>
#include <cassert>
#include <utility>
using namespace std;
#define MAXN 200050
int N;
char S[MAXN];
int Zaux[MAXN];
int Z[MAXN];
int RZ[MAXN];
bool flag;
long long ans;
// index idx in [a..b]
inline char getCh(int a, int b, int idx) {
return S[a + idx * (a <= b ? 1 : -1)];
}
// Z for [a..b] in [c..d]
void calcZ(int a, int b, int c, int d, int Z[MAXN]) {
int sz1 = abs(b - a) + 1;
int sz2 = abs(d - c) + 1;
int L = -1;
int R = -1;
Zaux[0] = sz2;
for (int i = 1; i < sz1; i++) {
if (i > R) {
L = R = i;
while (R < sz2 && R - L < sz2 && getCh(c, d, R) == getCh(c, d, R - L)) {
R++;
}
R--;
Zaux[i] = R - L + 1;
}
else {
int k = i - L;
Zaux[i] = min(Zaux[k], R - i + 1);
if (Zaux[i] == R - i + 1) {
L = i;
while (R < sz2 && R - L < sz2 && getCh(c, d, R) == getCh(c, d, R - L)) {
R++;
}
R--;
Zaux[i] = R - L + 1;
}
}
}
if (a <= b) {
L = R = -1;
for (int i = 0; i < sz1; i++) {
if (i > R) {
L = i;
R = i;
while (R < sz1 && R - L < sz2 && getCh(a, b, R) == getCh(c, d, R - L)) {
R++;
}
R--;
Z[i] = R - L + 1;
}
else {
int k = i - L;
Z[i] = min(Zaux[k], R - i + 1);
if (Z[i] == R - i + 1) {
L = i;
while (R < sz1 && R - L < sz2 && getCh(a, b, R) == getCh(c, d, R - L)) {
R++;
}
R--;
Z[i] = R - L + 1;
}
}
}
}
else { // a > b
for (int i = 0; i < sz1; i++) {
Z[i] = Zaux[sz1 - 1 - i];
}
}
}
void go(int st, int m, int dr) {
calcZ(st, m, m + 1, dr, Z);
calcZ(m, st, m, st, RZ);
int len = m - st + 1;
// printf("(%d, %d, %d) ->\n", st, m, dr);
// for (int i = 0; i < len; i++) { printf("%d ", Z[i]); } printf("\n");
// for (int i = 0; i < len; i++) { printf("%d ", RZ[i]); } printf("\n");
if (flag) {
for (int i = 0; i < len; i++) {
if (i + Z[i] == len) {
ans++;
}
}
}
for (int i = 1; i < len - 1; i++) {
int upper = min(i + Z[i], len - 1);
int lower = max(i + 1, len - RZ[i - 1]);
ans += max(0, upper - lower + 1);
}
}
void solve(int st, int dr) {
if (st == dr) {
return;
}
int m = (st + dr) / 2;
if (!flag) {
m = (st + dr - 1) / 2;
}
go(st, m, dr);
solve(st, m);
solve(m + 1, dr);
}
int brute() {
string ss(S);
int ret = 0;
for (int i = 0; i < N; i++) {
for (int j = 1; i + 2 * j - 1 < N; j++) {
if (ss.substr(i, j) == ss.substr(i + j, j)) {
ret++;
}
}
}
return ret;
}
int main() {
// freopen("date.in", "r", stdin);
// freopen("date.out","w", stdout);
fgets(S, sizeof(S), stdin);
N = strlen(S);
while (!isalpha(S[N - 1])) {
S[N - 1] = '\0';
N--;
}
// cout << brute() << endl;
ans = 0;
flag = true;
solve(0, N - 1);
reverse(S, S + N);
flag = false;
solve(0, N - 1);
cout << ans << endl;
// srand(time(0));
// for (int i = 0; i < 500; i++) {
// printf("%c", 'a' + rand() % 8);
// }
return 0;
}
I2luY2x1ZGUgPGNzdGRpbz4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8ZnN0cmVhbT4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGxpc3Q+CiNpbmNsdWRlIDxtYXA+CiNpbmNsdWRlIDxzZXQ+CiNpbmNsdWRlIDxxdWV1ZT4KI2luY2x1ZGUgPHN0YWNrPgojaW5jbHVkZSA8Yml0c2V0PgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8c3N0cmVhbT4KI2luY2x1ZGUgPGlvbWFuaXA+CiNpbmNsdWRlIDxjbWF0aD4KI2luY2x1ZGUgPGNzdGRsaWI+CiNpbmNsdWRlIDxjY3R5cGU+CiNpbmNsdWRlIDxjc3RyaW5nPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8Y3RpbWU+CiNpbmNsdWRlIDxjYXNzZXJ0PgojaW5jbHVkZSA8dXRpbGl0eT4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgojZGVmaW5lIE1BWE4gMjAwMDUwCgppbnQgTjsKY2hhciBTW01BWE5dOwppbnQgWmF1eFtNQVhOXTsKaW50IFpbTUFYTl07CmludCBSWltNQVhOXTsKYm9vbCBmbGFnOwpsb25nIGxvbmcgYW5zOwoKLy8gaW5kZXggaWR4IGluIFthLi5iXQppbmxpbmUgY2hhciBnZXRDaChpbnQgYSwgaW50IGIsIGludCBpZHgpIHsKCXJldHVybiBTW2EgKyBpZHggKiAoYSA8PSBiID8gMSA6IC0xKV07Cn0KCi8vIFogZm9yIFthLi5iXSBpbiBbYy4uZF0Kdm9pZCBjYWxjWihpbnQgYSwgaW50IGIsIGludCBjLCBpbnQgZCwgaW50IFpbTUFYTl0pIHsKCWludCBzejEgPSBhYnMoYiAtIGEpICsgMTsKCWludCBzejIgPSBhYnMoZCAtIGMpICsgMTsKCQoJaW50IEwgPSAtMTsKCWludCBSID0gLTE7CgkKCVphdXhbMF0gPSBzejI7Cglmb3IgKGludCBpID0gMTsgaSA8IHN6MTsgaSsrKSB7CgkJaWYgKGkgPiBSKSB7CgkJCUwgPSBSID0gaTsKCQkJd2hpbGUgKFIgPCBzejIgJiYgUiAtIEwgPCBzejIgJiYgZ2V0Q2goYywgZCwgUikgPT0gZ2V0Q2goYywgZCwgUiAtIEwpKSB7CgkJCQlSKys7CgkJCX0KCQkJUi0tOwoJCQlaYXV4W2ldID0gUiAtIEwgKyAxOwoJCX0KCQllbHNlIHsKCQkJaW50IGsgPSBpIC0gTDsKCQkJWmF1eFtpXSA9IG1pbihaYXV4W2tdLCBSIC0gaSArIDEpOwoJCQlpZiAoWmF1eFtpXSA9PSBSIC0gaSArIDEpIHsKCQkJCUwgPSBpOwoJCQkJd2hpbGUgKFIgPCBzejIgJiYgUiAtIEwgPCBzejIgJiYgZ2V0Q2goYywgZCwgUikgPT0gZ2V0Q2goYywgZCwgUiAtIEwpKSB7CgkJCQkJUisrOwoJCQkJfQoJCQkJUi0tOwoJCQkJWmF1eFtpXSA9IFIgLSBMICsgMTsKCQkJfQoJCX0KCX0KCQoJaWYgKGEgPD0gYikgewkKCQlMID0gUiA9IC0xOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgc3oxOyBpKyspIHsKCQkJaWYgKGkgPiBSKSB7CgkJCQlMID0gaTsKCQkJCVIgPSBpOwoJCQkJd2hpbGUgKFIgPCBzejEgJiYgUiAtIEwgPCBzejIgJiYgZ2V0Q2goYSwgYiwgUikgPT0gZ2V0Q2goYywgZCwgUiAtIEwpKSB7CgkJCQkJUisrOwoJCQkJfQoJCQkJUi0tOwoJCQkJWltpXSA9IFIgLSBMICsgMTsKCQkJfQoJCQllbHNlIHsKCQkJCWludCBrID0gaSAtIEw7CgkJCQlaW2ldID0gbWluKFphdXhba10sIFIgLSBpICsgMSk7CgkJCQlpZiAoWltpXSA9PSBSIC0gaSArIDEpIHsKCQkJCQlMID0gaTsKCQkJCQl3aGlsZSAoUiA8IHN6MSAmJiBSIC0gTCA8IHN6MiAmJiBnZXRDaChhLCBiLCBSKSA9PSBnZXRDaChjLCBkLCBSIC0gTCkpIHsKCQkJCQkJUisrOwoJCQkJCX0KCQkJCQlSLS07CgkJCQkJWltpXSA9IFIgLSBMICsgMTsKCQkJCX0KCQkJfQoJCX0KCX0KCWVsc2UgeyAvLyBhID4gYgoJCWZvciAoaW50IGkgPSAwOyBpIDwgc3oxOyBpKyspIHsKCQkJWltpXSA9IFphdXhbc3oxIC0gMSAtIGldOwoJCX0KCX0KfQoKdm9pZCBnbyhpbnQgc3QsIGludCBtLCBpbnQgZHIpIHsKCWNhbGNaKHN0LCBtLCBtICsgMSwgZHIsIFopOwoJY2FsY1oobSwgc3QsIG0sIHN0LCBSWik7CgkKCWludCBsZW4gPSBtIC0gc3QgKyAxOwoJCi8vCXByaW50ZigiKCVkLCAlZCwgJWQpIC0+XG4iLCBzdCwgbSwgZHIpOwovLwlmb3IgKGludCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7IHByaW50ZigiJWQgIiwgWltpXSk7IH0gcHJpbnRmKCJcbiIpOwovLwlmb3IgKGludCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7IHByaW50ZigiJWQgIiwgUlpbaV0pOyB9IHByaW50ZigiXG4iKTsKCQoJaWYgKGZsYWcpIHsKCQlmb3IgKGludCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7CgkJCWlmIChpICsgWltpXSA9PSBsZW4pIHsKCQkJCWFucysrOwoJCQl9CgkJfQoJfQoJCglmb3IgKGludCBpID0gMTsgaSA8IGxlbiAtIDE7IGkrKykgewoJCWludCB1cHBlciA9IG1pbihpICsgWltpXSwgbGVuIC0gMSk7CgkJaW50IGxvd2VyID0gbWF4KGkgKyAxLCBsZW4gLSBSWltpIC0gMV0pOwoJCWFucyArPSBtYXgoMCwgdXBwZXIgLSBsb3dlciArIDEpOwoJfQp9Cgp2b2lkIHNvbHZlKGludCBzdCwgaW50IGRyKSB7CglpZiAoc3QgPT0gZHIpIHsKCQlyZXR1cm47Cgl9CglpbnQgbSA9IChzdCArIGRyKSAvIDI7CglpZiAoIWZsYWcpIHsKCQltID0gKHN0ICsgZHIgLSAxKSAvIDI7Cgl9CgkKCWdvKHN0LCBtLCBkcik7CgkKCXNvbHZlKHN0LCBtKTsKCXNvbHZlKG0gKyAxLCBkcik7Cn0KCmludCBicnV0ZSgpIHsKCXN0cmluZyBzcyhTKTsKCWludCByZXQgPSAwOwoJZm9yIChpbnQgaSA9IDA7IGkgPCBOOyBpKyspIHsKCQlmb3IgKGludCBqID0gMTsgaSArIDIgKiBqIC0gMSA8IE47IGorKykgewoJCQlpZiAoc3Muc3Vic3RyKGksIGopID09IHNzLnN1YnN0cihpICsgaiwgaikpIHsKCQkJCXJldCsrOwoJCQl9CgkJfQoJfQoJcmV0dXJuIHJldDsKfQoKaW50IG1haW4oKSB7Ci8vCWZyZW9wZW4oImRhdGUuaW4iLCAiciIsIHN0ZGluKTsKLy8JZnJlb3BlbigiZGF0ZS5vdXQiLCJ3Iiwgc3Rkb3V0KTsKCQoJZmdldHMoUywgc2l6ZW9mKFMpLCBzdGRpbik7CglOID0gc3RybGVuKFMpOwoJd2hpbGUgKCFpc2FscGhhKFNbTiAtIDFdKSkgewoJCVNbTiAtIDFdID0gJ1wwJzsKCQlOLS07Cgl9CgkKLy8JY291dCA8PCBicnV0ZSgpIDw8IGVuZGw7CgkKCWFucyA9IDA7CglmbGFnID0gdHJ1ZTsKCXNvbHZlKDAsIE4gLSAxKTsKCQoJcmV2ZXJzZShTLCBTICsgTik7CglmbGFnID0gZmFsc2U7Cglzb2x2ZSgwLCBOIC0gMSk7CgkKCWNvdXQgPDwgYW5zIDw8IGVuZGw7CgkKLy8Jc3JhbmQodGltZSgwKSk7Ci8vCWZvciAoaW50IGkgPSAwOyBpIDwgNTAwOyBpKyspIHsKLy8JCXByaW50ZigiJWMiLCAnYScgKyByYW5kKCkgJSA4KTsKLy8JfQoJCglyZXR1cm4gMDsKfQo=