#pragma once
// This file is a fork of AtCoder Library.#define E6NLAQ_STRING_HPP
#include<algorithm>
#include<cassert>
#include<numeric>
#include<string>
#include<vector>namespacee6nlaq{namespaceinternal{inlinestd::vector<int>sa_naive(conststd::vector<int>&s){intn=int(s.size());std::vector<int>sa(n);std::iota(sa.begin(),sa.end(),0);std::sort(sa.begin(),sa.end(),[&](intl,intr){if(l==r)returnfalse;while(l<n&&r<n){if(s[l]!=s[r])returns[l]<s[r];l++;r++;}returnl==n;});returnsa;}inlinestd::vector<int>sa_doubling(conststd::vector<int>&s){intn=int(s.size());std::vector<int>sa(n),rnk=s,tmp(n);std::iota(sa.begin(),sa.end(),0);for(intk=1;k<n;k*=2){autocmp=[&](intx,inty){if(rnk[x]!=rnk[y])returnrnk[x]<rnk[y];intrx=x+k<n?rnk[x+k]:-1;intry=y+k<n?rnk[y+k]:-1;returnrx<ry;};std::sort(sa.begin(),sa.end(),cmp);tmp[sa[0]]=0;for(inti=1;i<n;i++){tmp[sa[i]]=tmp[sa[i-1]]+(cmp(sa[i-1],sa[i])?1:0);}std::swap(tmp,rnk);}returnsa;}// SA-IS, linear-time suffix array construction// Reference:// G. Nong, S. Zhang, and W. H. Chan,// Two Efficient Algorithms for Linear Time Suffix Array Constructiontemplate<intTHRESHOLD_NAIVE=10,intTHRESHOLD_DOUBLING=40>std::vector<int>sa_is(conststd::vector<int>&s,intupper){intn=int(s.size());if(n==0)return{};if(n==1)return{0};if(n==2){if(s[0]<s[1]){return{0,1};}else{return{1,0};}}if(n<THRESHOLD_NAIVE){returnsa_naive(s);}if(n<THRESHOLD_DOUBLING){returnsa_doubling(s);}std::vector<int>sa(n);std::vector<bool>ls(n);for(inti=n-2;i>=0;i--){ls[i]=(s[i]==s[i+1])?ls[i+1]:(s[i]<s[i+1]);}std::vector<int>sum_l(upper+1),sum_s(upper+1);for(inti=0;i<n;i++){if(!ls[i]){sum_s[s[i]]++;}else{sum_l[s[i]+1]++;}}for(inti=0;i<=upper;i++){sum_s[i]+=sum_l[i];if(i<upper)sum_l[i+1]+=sum_s[i];}autoinduce=[&](conststd::vector<int>&lms){std::fill(sa.begin(),sa.end(),-1);std::vector<int>buf(upper+1);std::copy(sum_s.begin(),sum_s.end(),buf.begin());for(autod:lms){if(d==n)continue;sa[buf[s[d]]++]=d;}std::copy(sum_l.begin(),sum_l.end(),buf.begin());sa[buf[s[n-1]]++]=n-1;for(inti=0;i<n;i++){intv=sa[i];if(v>=1&&!ls[v-1]){sa[buf[s[v-1]]++]=v-1;}}std::copy(sum_l.begin(),sum_l.end(),buf.begin());for(inti=n-1;i>=0;i--){intv=sa[i];if(v>=1&&ls[v-1]){sa[--buf[s[v-1]+1]]=v-1;}}};std::vector<int>lms_map(n+1,-1);intm=0;for(inti=1;i<n;i++){if(!ls[i-1]&&ls[i]){lms_map[i]=m++;}}std::vector<int>lms;lms.reserve(m);for(inti=1;i<n;i++){if(!ls[i-1]&&ls[i]){lms.push_back(i);}}induce(lms);if(m){std::vector<int>sorted_lms;sorted_lms.reserve(m);for(intv:sa){if(lms_map[v]!=-1)sorted_lms.push_back(v);}std::vector<int>rec_s(m);intrec_upper=0;rec_s[lms_map[sorted_lms[0]]]=0;for(inti=1;i<m;i++){intl=sorted_lms[i-1],r=sorted_lms[i];intend_l=(lms_map[l]+1<m)?lms[lms_map[l]+1]:n;intend_r=(lms_map[r]+1<m)?lms[lms_map[r]+1]:n;boolsame=true;if(end_l-l!=end_r-r){same=false;}else{while(l<end_l){if(s[l]!=s[r]){break;}l++;r++;}if(l==n||s[l]!=s[r])same=false;}if(!same)rec_upper++;rec_s[lms_map[sorted_lms[i]]]=rec_upper;}autorec_sa=sa_is<THRESHOLD_NAIVE,THRESHOLD_DOUBLING>(rec_s,rec_upper);for(inti=0;i<m;i++){sorted_lms[i]=lms[rec_sa[i]];}induce(sorted_lms);}returnsa;}}// namespace internalinlinestd::vector<int>suffix_array(conststd::vector<int>&s,intupper){assert(0<=upper);for(intd:s){assert(0<=d&&d<=upper);}autosa=internal::sa_is(s,upper);returnsa;}template<classT>std::vector<int>suffix_array(conststd::vector<T>&s){intn=int(s.size());std::vector<int>idx(n);iota(idx.begin(),idx.end(),0);sort(idx.begin(),idx.end(),[&](intl,intr){returns[l]<s[r];});std::vector<int>s2(n);intnow=0;for(inti=0;i<n;i++){if(i&&s[idx[i-1]]!=s[idx[i]])now++;s2[idx[i]]=now;}returninternal::sa_is(s2,now);}inlinestd::vector<int>suffix_array(conststd::string&s){intn=int(s.size());std::vector<int>s2(n);for(inti=0;i<n;i++){s2[i]=s[i];}returninternal::sa_is(s2,255);}// Reference:// T. Kasai, G. Lee, H. Arimura, S. Arikawa, and K. Park,// Linear-Time Longest-Common-Prefix Computation in Suffix Arrays and Its// Applicationstemplate<classT>std::vector<int>lcp_array(conststd::vector<T>&s,conststd::vector<int>&sa){intn=int(s.size());assert(n>=1);std::vector<int>rnk(n);for(inti=0;i<n;i++){rnk[sa[i]]=i;}std::vector<int>lcp(n-1);inth=0;for(inti=0;i<n;i++){if(h>0)h--;if(rnk[i]==0)continue;intj=sa[rnk[i]-1];for(;j+h<n&&i+h<n;h++){if(s[j+h]!=s[i+h])break;}lcp[rnk[i]-1]=h;}returnlcp;}inlinestd::vector<int>lcp_array(conststd::string&s,conststd::vector<int>&sa){intn=int(s.size());std::vector<int>s2(n);for(inti=0;i<n;i++){s2[i]=s[i];}returnlcp_array(s2,sa);}// Reference:// D. Gusfield,// Algorithms on Strings, Trees, and Sequences: Computer Science and// Computational Biologytemplate<classT>std::vector<int>z_algorithm(conststd::vector<T>&s){intn=int(s.size());if(n==0)return{};std::vector<int>z(n);z[0]=0;for(inti=1,j=0;i<n;i++){int&k=z[i];k=(j+z[j]<=i)?0:std::min(j+z[j]-i,z[i-j]);while(i+k<n&&s[k]==s[i+k])k++;if(j+z[j]<i+z[i])j=i;}z[0]=n;returnz;}inlinestd::vector<int>z_algorithm(conststd::string&s){intn=int(s.size());std::vector<int>s2(n);for(inti=0;i<n;i++){s2[i]=s[i];}returnz_algorithm(s2);}}// namespace e6nlaq
#line 2 "include/e6nlaq/string.hpp"
// This file is a fork of AtCoder Library.#define E6NLAQ_STRING_HPP
#include<algorithm>
#include<cassert>
#include<numeric>
#include<string>
#include<vector>namespacee6nlaq{namespaceinternal{inlinestd::vector<int>sa_naive(conststd::vector<int>&s){intn=int(s.size());std::vector<int>sa(n);std::iota(sa.begin(),sa.end(),0);std::sort(sa.begin(),sa.end(),[&](intl,intr){if(l==r)returnfalse;while(l<n&&r<n){if(s[l]!=s[r])returns[l]<s[r];l++;r++;}returnl==n;});returnsa;}inlinestd::vector<int>sa_doubling(conststd::vector<int>&s){intn=int(s.size());std::vector<int>sa(n),rnk=s,tmp(n);std::iota(sa.begin(),sa.end(),0);for(intk=1;k<n;k*=2){autocmp=[&](intx,inty){if(rnk[x]!=rnk[y])returnrnk[x]<rnk[y];intrx=x+k<n?rnk[x+k]:-1;intry=y+k<n?rnk[y+k]:-1;returnrx<ry;};std::sort(sa.begin(),sa.end(),cmp);tmp[sa[0]]=0;for(inti=1;i<n;i++){tmp[sa[i]]=tmp[sa[i-1]]+(cmp(sa[i-1],sa[i])?1:0);}std::swap(tmp,rnk);}returnsa;}// SA-IS, linear-time suffix array construction// Reference:// G. Nong, S. Zhang, and W. H. Chan,// Two Efficient Algorithms for Linear Time Suffix Array Constructiontemplate<intTHRESHOLD_NAIVE=10,intTHRESHOLD_DOUBLING=40>std::vector<int>sa_is(conststd::vector<int>&s,intupper){intn=int(s.size());if(n==0)return{};if(n==1)return{0};if(n==2){if(s[0]<s[1]){return{0,1};}else{return{1,0};}}if(n<THRESHOLD_NAIVE){returnsa_naive(s);}if(n<THRESHOLD_DOUBLING){returnsa_doubling(s);}std::vector<int>sa(n);std::vector<bool>ls(n);for(inti=n-2;i>=0;i--){ls[i]=(s[i]==s[i+1])?ls[i+1]:(s[i]<s[i+1]);}std::vector<int>sum_l(upper+1),sum_s(upper+1);for(inti=0;i<n;i++){if(!ls[i]){sum_s[s[i]]++;}else{sum_l[s[i]+1]++;}}for(inti=0;i<=upper;i++){sum_s[i]+=sum_l[i];if(i<upper)sum_l[i+1]+=sum_s[i];}autoinduce=[&](conststd::vector<int>&lms){std::fill(sa.begin(),sa.end(),-1);std::vector<int>buf(upper+1);std::copy(sum_s.begin(),sum_s.end(),buf.begin());for(autod:lms){if(d==n)continue;sa[buf[s[d]]++]=d;}std::copy(sum_l.begin(),sum_l.end(),buf.begin());sa[buf[s[n-1]]++]=n-1;for(inti=0;i<n;i++){intv=sa[i];if(v>=1&&!ls[v-1]){sa[buf[s[v-1]]++]=v-1;}}std::copy(sum_l.begin(),sum_l.end(),buf.begin());for(inti=n-1;i>=0;i--){intv=sa[i];if(v>=1&&ls[v-1]){sa[--buf[s[v-1]+1]]=v-1;}}};std::vector<int>lms_map(n+1,-1);intm=0;for(inti=1;i<n;i++){if(!ls[i-1]&&ls[i]){lms_map[i]=m++;}}std::vector<int>lms;lms.reserve(m);for(inti=1;i<n;i++){if(!ls[i-1]&&ls[i]){lms.push_back(i);}}induce(lms);if(m){std::vector<int>sorted_lms;sorted_lms.reserve(m);for(intv:sa){if(lms_map[v]!=-1)sorted_lms.push_back(v);}std::vector<int>rec_s(m);intrec_upper=0;rec_s[lms_map[sorted_lms[0]]]=0;for(inti=1;i<m;i++){intl=sorted_lms[i-1],r=sorted_lms[i];intend_l=(lms_map[l]+1<m)?lms[lms_map[l]+1]:n;intend_r=(lms_map[r]+1<m)?lms[lms_map[r]+1]:n;boolsame=true;if(end_l-l!=end_r-r){same=false;}else{while(l<end_l){if(s[l]!=s[r]){break;}l++;r++;}if(l==n||s[l]!=s[r])same=false;}if(!same)rec_upper++;rec_s[lms_map[sorted_lms[i]]]=rec_upper;}autorec_sa=sa_is<THRESHOLD_NAIVE,THRESHOLD_DOUBLING>(rec_s,rec_upper);for(inti=0;i<m;i++){sorted_lms[i]=lms[rec_sa[i]];}induce(sorted_lms);}returnsa;}}// namespace internalinlinestd::vector<int>suffix_array(conststd::vector<int>&s,intupper){assert(0<=upper);for(intd:s){assert(0<=d&&d<=upper);}autosa=internal::sa_is(s,upper);returnsa;}template<classT>std::vector<int>suffix_array(conststd::vector<T>&s){intn=int(s.size());std::vector<int>idx(n);iota(idx.begin(),idx.end(),0);sort(idx.begin(),idx.end(),[&](intl,intr){returns[l]<s[r];});std::vector<int>s2(n);intnow=0;for(inti=0;i<n;i++){if(i&&s[idx[i-1]]!=s[idx[i]])now++;s2[idx[i]]=now;}returninternal::sa_is(s2,now);}inlinestd::vector<int>suffix_array(conststd::string&s){intn=int(s.size());std::vector<int>s2(n);for(inti=0;i<n;i++){s2[i]=s[i];}returninternal::sa_is(s2,255);}// Reference:// T. Kasai, G. Lee, H. Arimura, S. Arikawa, and K. Park,// Linear-Time Longest-Common-Prefix Computation in Suffix Arrays and Its// Applicationstemplate<classT>std::vector<int>lcp_array(conststd::vector<T>&s,conststd::vector<int>&sa){intn=int(s.size());assert(n>=1);std::vector<int>rnk(n);for(inti=0;i<n;i++){rnk[sa[i]]=i;}std::vector<int>lcp(n-1);inth=0;for(inti=0;i<n;i++){if(h>0)h--;if(rnk[i]==0)continue;intj=sa[rnk[i]-1];for(;j+h<n&&i+h<n;h++){if(s[j+h]!=s[i+h])break;}lcp[rnk[i]-1]=h;}returnlcp;}inlinestd::vector<int>lcp_array(conststd::string&s,conststd::vector<int>&sa){intn=int(s.size());std::vector<int>s2(n);for(inti=0;i<n;i++){s2[i]=s[i];}returnlcp_array(s2,sa);}// Reference:// D. Gusfield,// Algorithms on Strings, Trees, and Sequences: Computer Science and// Computational Biologytemplate<classT>std::vector<int>z_algorithm(conststd::vector<T>&s){intn=int(s.size());if(n==0)return{};std::vector<int>z(n);z[0]=0;for(inti=1,j=0;i<n;i++){int&k=z[i];k=(j+z[j]<=i)?0:std::min(j+z[j]-i,z[i-j]);while(i+k<n&&s[k]==s[i+k])k++;if(j+z[j]<i+z[i])j=i;}z[0]=n;returnz;}inlinestd::vector<int>z_algorithm(conststd::string&s){intn=int(s.size());std::vector<int>s2(n);for(inti=0;i<n;i++){s2[i]=s[i];}returnz_algorithm(s2);}}// namespace e6nlaq