#include using namespace std; typedef long long ll; typedef vector vi; typedef vector vl; typedef pair pii; typedef pair pll; typedef int _loop_int; #define REP(i,n) for(_loop_int i=0;i<(_loop_int)(n);++i) #define FOR(i,a,b) for(_loop_int i=(_loop_int)(a);i<(_loop_int)(b);++i) #define FORR(i,a,b) for(_loop_int i=(_loop_int)(b)-1;i>=(_loop_int)(a);--i) #define DEBUG(x) cout<<#x<<": "< P; int n; char s[525252]; // manacher int m; char ss[1252525]; int mana[1252525]; ll tailpal[525252]; inline bool pal(int l,int r){ return mana[r+l-1] > r-l-1; } ll pl[525252]; ll gpl[525252]; int main(){ scanf("%s",s); n = strlen(s); for(int i=0;i=0 && i+j=0 && i+k0;i--){ tailpal[i-1] = tailpal[i] + (mana[n+i-1]>n-i-1); } // 解説を読みました……>< // https://arxiv.org/pdf/1403.2431v2.pdf // pp.11 typedef pair trip; #define X first #define Y second.first #define Z second.second #define PACK(x,y,z) trip(x,pii(y,z)) #define UNPACK(x,y,z,t) int x=(t).X,y=(t).Y,z=(t).Z vector G,G2; FOR(j,1,n+1){ G2.clear(); for(auto T:G){ UNPACK(x,y,z,T); // palindrome if(x>1 && s[x-2]==s[j-1]){ G2.push_back(PACK(x-1,y,z)); } } swap(G,G2); G2.clear(); int r = -j; for(auto T:G){ UNPACK(x,y,z,T); if(x-r != y){ G2.push_back(PACK(x,x-r,1)); if(z>1){ G2.push_back(PACK(x+y,y,z-1)); } }else{ G2.push_back(T); } r = x + (z-1)*y; } if(j>1 && s[j-2]==s[j-1]){ G2.push_back(PACK(j-1,j-1-r,1)); r = j-1; } G2.push_back(PACK(j,j-r,1)); G.clear(); auto fst = G2[0]; UNPACK(xx,yy,zz,fst); bool flag = true; for(auto T:G2){ if(flag){ flag=false; continue; } UNPACK(x,y,z,T); if(y==yy){ zz += z; }else{ G.push_back(PACK(xx,yy,zz)); xx = x; yy = y; zz = z; } } G.push_back(PACK(xx,yy,zz)); // modify for split palindrome // 元 : prefixを最小のpalindromeで構成する 数:pl[i] // 新 : PPと分解する数 // 周期性のあるpalindromeで表せるため計算が使いまわせる、らしい // pl[j] = j; pl[j-1] = 0; for(auto T:G){ UNPACK(x,y,z,T); r = x + (z-1)*y; // int mm = pl[r-1]+1; // 最小周期でPPと分割 ll mm = 0; if(r>=2 && pal(0,r-2+1))mm = 1; // 周期1つ戻した計算結果を再利用 if(z>1){ // CHMIN(mm,gpl[x-z]); mm += gpl[x-y]; } // メモ if(y<=x){ gpl[x-y] = mm; } // CHMIN(pl[j],mm); pl[j-1] += mm; } } ll ans = 0; FOR(i,1,n-1){ ans += pl[i] * tailpal[i+1]; } printf("%lld\n",ans); // 難しい>< return 0; }