#pragma once
#include<atcoder/string>usingnamespaceatcoder;#define SIZE_(s) int(s.size())
structRunEnumerate{std::strings;RunEnumerate(conststd::string&s):s(s){build();}structRun{intt,l,r;Run()=default;Run(intt,intl,intr):t(t),l(l),r(r){}};std::vector<Run>ans;std::queue<std::pair<int,int>>que;std::stringREV(std::strings){std::ranges::reverse(s);returns;}voidsolve(intl,intr){intm=(l+r)>>1;que.emplace(l,m);que.emplace(m,r);std::stringleft_s=s.substr(l,m-l),right_s=s.substr(m,r-m),all_s=s.substr(l,r-l);{// 各 k に対し、left_s の suffix t 文字を周期とする run を探すautoZ_left_rev=z_algorithm(REV(left_s));autoLeft=[&](intt)->int{// [*,m) が周期 tif(t==SIZE_(left_s))returnl;returnm-t-Z_left_rev[t];};autoZ_right=z_algorithm(right_s+"#"+all_s);autoRight=[&](intt)->int{// [m,*)returnm+Z_right[r-l-t+1];};for(intt=1;t<=m-l;t++){intL=Left(t),R=Right(t);if(R-L>=2*t)ans.emplace_back(t,L,R);}}{// [m,r) の prefix t 文字autoZ_right=z_algorithm(right_s);autoRight=[&](intt)->int{if(t==SIZE_(right_s))returnr;returnm+t+Z_right[t];};autoZ_left=z_algorithm(REV(left_s)+"#"+REV(all_s));autoLeft=[&](intt)->int{returnm-Z_left[SIZE_(Z_left)-SIZE_(left_s)-t];};for(intt=1;t<=r-m;t++){intL=Left(t),R=Right(t);if(R-L>=2*t)ans.emplace_back(t,L,R);}}}voidarrangement(){std::vector<Run>fans;std::ranges::sort(ans,[](Runa,Runb){if(a.t!=b.t)returna.t<b.t;if(a.l!=b.l)returna.l<b.l;returna.r>b.r;});std::set<std::pair<int,int>>already;intpret=-1,mx;for(constauto&[t,l,r]:ans){if(pret!=t)pret=t,mx=-1;if(already.count({l,r})||mx>=r)continue;if((r<SIZE_(s)ands[r]==s[r-t])or(l-1>=0ands[l-1]==s[l-1+t]))continue;fans.emplace_back(t,l,r);already.emplace(l,r);mx=r;}ans=fans;}voidbuild(){que.emplace(0,int(s.size()));while(que.size()){auto[l,r]=que.front();que.pop();if(l+1==r)continue;solve(l,r);}arrangement();}};#undef SIZE_
#line 2 "library/sequence/RunEnumerate.hpp"
#include<atcoder/string>usingnamespaceatcoder;#define SIZE_(s) int(s.size())
structRunEnumerate{std::strings;RunEnumerate(conststd::string&s):s(s){build();}structRun{intt,l,r;Run()=default;Run(intt,intl,intr):t(t),l(l),r(r){}};std::vector<Run>ans;std::queue<std::pair<int,int>>que;std::stringREV(std::strings){std::ranges::reverse(s);returns;}voidsolve(intl,intr){intm=(l+r)>>1;que.emplace(l,m);que.emplace(m,r);std::stringleft_s=s.substr(l,m-l),right_s=s.substr(m,r-m),all_s=s.substr(l,r-l);{// 各 k に対し、left_s の suffix t 文字を周期とする run を探すautoZ_left_rev=z_algorithm(REV(left_s));autoLeft=[&](intt)->int{// [*,m) が周期 tif(t==SIZE_(left_s))returnl;returnm-t-Z_left_rev[t];};autoZ_right=z_algorithm(right_s+"#"+all_s);autoRight=[&](intt)->int{// [m,*)returnm+Z_right[r-l-t+1];};for(intt=1;t<=m-l;t++){intL=Left(t),R=Right(t);if(R-L>=2*t)ans.emplace_back(t,L,R);}}{// [m,r) の prefix t 文字autoZ_right=z_algorithm(right_s);autoRight=[&](intt)->int{if(t==SIZE_(right_s))returnr;returnm+t+Z_right[t];};autoZ_left=z_algorithm(REV(left_s)+"#"+REV(all_s));autoLeft=[&](intt)->int{returnm-Z_left[SIZE_(Z_left)-SIZE_(left_s)-t];};for(intt=1;t<=r-m;t++){intL=Left(t),R=Right(t);if(R-L>=2*t)ans.emplace_back(t,L,R);}}}voidarrangement(){std::vector<Run>fans;std::ranges::sort(ans,[](Runa,Runb){if(a.t!=b.t)returna.t<b.t;if(a.l!=b.l)returna.l<b.l;returna.r>b.r;});std::set<std::pair<int,int>>already;intpret=-1,mx;for(constauto&[t,l,r]:ans){if(pret!=t)pret=t,mx=-1;if(already.count({l,r})||mx>=r)continue;if((r<SIZE_(s)ands[r]==s[r-t])or(l-1>=0ands[l-1]==s[l-1+t]))continue;fans.emplace_back(t,l,r);already.emplace(l,r);mx=r;}ans=fans;}voidbuild(){que.emplace(0,int(s.size()));while(que.size()){auto[l,r]=que.front();que.pop();if(l+1==r)continue;solve(l,r);}arrangement();}};#undef SIZE_