#pragma GCC optimize("O3")
// RollingHash
// https://w...content-available-to-author-only...c.net/problem/1605
#include<bits/stdc++.h>
using namespace std;
// https://q...content-available-to-author-only...a.com/recuraki/items/652f97f5330fde231ddb#%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E8%A1%9D%E7%AA%81%E6%94%BB%E6%92%83%E3%81%AE%E3%83%8F%E3%83%83%E3%82%AD%E3%83%B3%E3%82%B0%E3%81%8B%E3%82%89%E8%BA%AB%E3%82%92%E5%AE%88%E3%82%8B%E6%96%B9%E6%B3%95
#include <chrono>
struct custom_hash {
static uint64_t splitmix64(uint64_t x) {
// http://x...content-available-to-author-only...i.it/splitmix64.c
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const {
static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}
};
// Safer-Faster-RollingHash
// https://q...content-available-to-author-only...a.com/keymoon/items/11fac5627672a6d6a9f6
// https://a...content-available-to-author-only...r.jp/contests/abc141/submissions/7717102
typedef unsigned long long int ull;
#define MAXLEN 500005
const ull MASK30 = (1ull << 30) - 1;
const ull MASK31 = (1ull << 31) - 1;
const ull MOD = (1ull << 61) - 1;
const ull MASK61 = MOD;
const ull POSITIVIZER = MOD * 4;
//mod 2^61-1
ull CalcMod(ull x)
{
ull xu = x >> 61;
ull xd = x & MASK61;
ull res = xu + xd;
if (res >= MOD) res -= MOD;
return res;
}
//a*b mod 2^61-1
ull Mul(ull a, ull b)
{
ull au = a >> 31;
ull ad = a & MASK31;
ull bu = b >> 31;
ull bd = b & MASK31;
ull mid = ad * bu + au * bd;
ull midu = mid >> 30;
ull midd = mid & MASK30;
return CalcMod(au * bu * 2 + midu + (midd << 31) + ad * bd);
}
ull hBase;
vector<ull> powMemo;
void genBase(mt19937_64 &eg){
hBase=0;
while(hBase==0){
hBase=CalcMod((ull)eg());
}
powMemo.resize(MAXLEN);
powMemo[0]=1;
for(int i=1;i<MAXLEN;i++){
powMemo[i]=Mul(powMemo[i-1],hBase);
}
}
vector<ull> genHash(string s){
vector<ull> res={0};
ull cur=0;
for(auto &nx : s){
cur=Mul(cur,hBase);
cur=CalcMod(cur+nx);
res.push_back(cur);
}
return res;
}
// substr [l,r) (0-indexed)
ull subHash(int l,int r,vector<ull> &hv){
return CalcMod(hv[r] + POSITIVIZER - Mul(hv[l], powMemo[r-l]));
}
int main(){
random_device seed_gen;
mt19937_64 engine(seed_gen());
genBase(engine);
ios::sync_with_stdio(false);
cin.tie(nullptr);
while(true){
string s;
cin >> s;
if(s[0]=='0'){break;}
long long res=0;
int l=s.size();
vector<ull> hv=genHash(s);
for(int u=1;u<=(l/2);u++){
bool pre=false;
int f=(u-1);
while(f+u<l){
int s=(f+u);
int lef=1,rig=u;
while(lef<=rig){
int te=(lef+rig)/2;
if(subHash(f+1-te,f+1,hv)==subHash(s+1-te,s+1,hv)){lef=te+1;}
else{rig=te-1;}
}
if(rig==u){
// match
if(pre){res+=u;}
else{res++;}
pre=true;
f=s;
}
else{
if(pre){
int ulef=1,urig=u;
while(ulef<=urig){
int te=(ulef+urig)/2;
if(subHash(f+1-u,f+1+te-u,hv)==subHash(f+1,f+1+te,hv)){ulef=te+1;}
else{urig=te-1;}
}
res+=urig;
}
pre=false;
f=s-rig;
}
}
if(pre){
int ulef=1,urig=u;
while(ulef<=urig){
int te=(ulef+urig)/2;
if(f+1+te>l){urig=te-1; continue;}
if(subHash(f+1-u,f+1+te-u,hv)==subHash(f+1,f+1+te,hv)){ulef=te+1;}
else{urig=te-1;}
}
res+=urig;
}
}
cout << res << "\n";
}
}