#line 1 "verify/string/string_algorithms.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/aplusb"
#line 1 "string/all.hpp"
#line 1 "string/aho_corasick.hpp"
#include<array>
#include<cassert>
#include<cstddef>
#include<limits>
#include<queue>
#include<vector>namespacem1une{namespacestring{// Aho-Corasick automaton for a contiguous character alphabet.template<intAlphabetSize=26,intFirstCharacter='a'>structAhoCorasick{static_assert(0<AlphabetSize);usingnode_id=int;staticconstexprnode_idnull_node=-1;structNode{// Completed automaton transitions. Valid after build().std::array<node_id,AlphabetSize>next;node_idfailure;node_idoutput_link;node_idparent;intparent_symbol;intdepth;std::vector<node_id>children;std::vector<node_id>failure_children;std::vector<int>pattern_ids;Node(node_idparent_value=null_node,intparent_symbol_value=-1,intdepth_value=0):failure(0),output_link(null_node),parent(parent_value),parent_symbol(parent_symbol_value),depth(depth_value){next.fill(null_node);}};private:std::vector<Node>_nodes;std::vector<int>_pattern_length;std::vector<node_id>_pattern_node;std::vector<node_id>_bfs_order;bool_built;template<classSymbol>staticintsymbol_index(constSymbol&symbol){intindex=int(symbol)-FirstCharacter;assert(0<=index&&index<AlphabetSize);returnindex;}node_idnew_node(node_idparent,intparent_symbol){assert(_nodes.size()<std::size_t(std::numeric_limits<int>::max()));assert(_nodes[parent].depth<std::numeric_limits<int>::max());_nodes.emplace_back(parent,parent_symbol,_nodes[parent].depth+1);returnint(_nodes.size())-1;}public:AhoCorasick():_nodes(1),_built(false){}node_idroot()const{return0;}boolbuilt()const{return_built;}intpattern_count()const{returnint(_pattern_length.size());}intpattern_length(intpattern_id)const{assert(0<=pattern_id&&pattern_id<pattern_count());return_pattern_length[pattern_id];}node_idpattern_node(intpattern_id)const{assert(0<=pattern_id&&pattern_id<pattern_count());return_pattern_node[pattern_id];}std::size_tnode_count()const{return_nodes.size();}conststd::vector<Node>&nodes()const{return_nodes;}constNode&node(node_idid)const{assert(0<=id&&std::size_t(id)<_nodes.size());return_nodes[id];}// Returns nodes in failure-link BFS order, beginning with the root.conststd::vector<node_id>&bfs_order()const{assert(_built);return_bfs_order;}voidreserve(std::size_tnode_capacity){assert(!_built);_nodes.reserve(node_capacity);}voidclear(){_nodes.clear();_nodes.emplace_back();_pattern_length.clear();_pattern_node.clear();_bfs_order.clear();_built=false;}// Inserts a pattern and returns its insertion-order ID.template<classSequence>intinsert(constSequence&pattern){assert(!_built);intpattern_id=pattern_count();intlength=0;node_idstate=root();for(constauto&symbol:pattern){assert(length<std::numeric_limits<int>::max());intindex=symbol_index(symbol);if(_nodes[state].next[index]==null_node){node_idchild=new_node(state,index);_nodes[state].next[index]=child;_nodes[state].children.push_back(child);}state=_nodes[state].next[index];length++;}_nodes[state].pattern_ids.push_back(pattern_id);_pattern_length.push_back(length);_pattern_node.push_back(state);returnpattern_id;}// Builds failure links and completes every automaton transition.voidbuild(){assert(!_built);std::queue<node_id>queue;_bfs_order.clear();_bfs_order.reserve(_nodes.size());_bfs_order.push_back(root());for(intsymbol=0;symbol<AlphabetSize;++symbol){node_idchild=_nodes[root()].next[symbol];if(child==null_node){_nodes[root()].next[symbol]=root();}else{_nodes[root()].next[symbol]=child;_nodes[child].failure=root();_nodes[child].output_link=_nodes[root()].pattern_ids.empty()?null_node:root();_nodes[root()].failure_children.push_back(child);queue.push(child);}}while(!queue.empty()){node_idstate=queue.front();queue.pop();_bfs_order.push_back(state);for(intsymbol=0;symbol<AlphabetSize;++symbol){node_idchild=_nodes[state].next[symbol];if(child==null_node){_nodes[state].next[symbol]=_nodes[_nodes[state].failure].next[symbol];continue;}_nodes[state].next[symbol]=child;node_idfailure=_nodes[_nodes[state].failure].next[symbol];_nodes[child].failure=failure;_nodes[child].output_link=_nodes[failure].pattern_ids.empty()?_nodes[failure].output_link:failure;_nodes[failure].failure_children.push_back(child);queue.push(child);}}_built=true;}template<classSymbol>node_idtransition(node_idstate,constSymbol&symbol)const{assert(_built);assert(0<=state&&std::size_t(state)<_nodes.size());return_nodes[state].next[symbol_index(symbol)];}// Calls callback(pattern_id) for every pattern ending at `state`.template<classCallback>voidfor_each_output(node_idstate,Callbackcallback)const{assert(_built);assert(0<=state&&std::size_t(state)<_nodes.size());while(state!=null_node){for(intpattern_id:_nodes[state].pattern_ids){callback(pattern_id);}state=_nodes[state].output_link;}}// Calls callback(end, pattern_id) for every occurrence. `end` is the// exclusive end position. Empty patterns occur at every text boundary.template<classSequence,classCallback>voidmatch(constSequence&text,Callbackcallback)const{assert(_built);node_idstate=root();for_each_output(state,[&callback](intpattern_id){callback(0,pattern_id);});intend=0;for(constauto&symbol:text){state=transition(state,symbol);end++;for_each_output(state,[&callback,end](intpattern_id){callback(end,pattern_id);});}}// Counts occurrences of every inserted pattern in linear time.template<classSequence>std::vector<longlong>count_occurrences(constSequence&text)const{assert(_built);std::vector<longlong>visits(_nodes.size(),0);node_idstate=root();visits[root()]++;for(constauto&symbol:text){state=transition(state,symbol);visits[state]++;}for(std::size_tindex=_bfs_order.size();index-->1;){node_idcurrent=_bfs_order[index];visits[_nodes[current].failure]+=visits[current];}std::vector<longlong>result(pattern_count(),0);for(node_idcurrent:_bfs_order){for(intpattern_id:_nodes[current].pattern_ids){result[pattern_id]=visits[current];}}returnresult;}};}// namespace string}// namespace m1une#line 1 "string/deque_eertree.hpp"
#line 7 "string/deque_eertree.hpp"
#include<deque>
#line 10 "string/deque_eertree.hpp"
namespacem1une{namespacestring{template<intAlphabetSize=26,intFirstCharacter='a'>structDequeEertree{static_assert(0<AlphabetSize);usingnode_id=int;staticconstexprnode_idodd_root=0;staticconstexprnode_ideven_root=1;staticconstexprnode_idnull_node=-1;private:structNode{std::array<node_id,AlphabetSize>next;node_idparent;node_idsuffix_link;node_idquick_link;intlength;intsurface_count;intsuffix_link_children;boolactive;Node(intlength_value=0,node_idparent_value=null_node,node_idsuffix_link_value=null_node,node_idquick_link_value=null_node):parent(parent_value),suffix_link(suffix_link_value),quick_link(quick_link_value),length(length_value),surface_count(0),suffix_link_children(0),active(true){next.fill(null_node);}};structPosition{intsymbol;node_idprefix_surface;node_idsuffix_surface;};std::vector<Node>_nodes;std::deque<Position>_text;int_distinct_palindromes;template<classSymbol>staticintsymbol_index(constSymbol&value){intsymbol=int(value)-FirstCharacter;assert(0<=symbol&&symbol<AlphabetSize);returnsymbol;}node_idnew_node(node_idparent,node_idsuffix_link,intlength,intsymbol){assert(_nodes.size()<std::size_t(std::numeric_limits<int>::max()));node_idid=int(_nodes.size());_nodes.emplace_back(length,parent,suffix_link,odd_root);_nodes[parent].next[symbol]=id;_nodes[suffix_link].suffix_link_children++;_distinct_palindromes++;returnid;}voidremove_node(node_idid,intsymbol){Node&removed=_nodes[id];assert(removed.active);assert(removed.surface_count==0);assert(removed.suffix_link_children==0);assert(_nodes[removed.parent].next[symbol]==id);_nodes[removed.parent].next[symbol]=null_node;_nodes[removed.suffix_link].suffix_link_children--;removed.active=false;_distinct_palindromes--;}node_idback_appendable(intsymbol,node_idnode)const{intn=int(_text.size());while(true){intlength=_nodes[node].length;if(length==-1||(length<n&&_text[n-length-1].symbol==symbol)){returnnode;}node_idsuffix=_nodes[node].suffix_link;intsuffix_length=_nodes[suffix].length;if(suffix_length==-1||_text[n-suffix_length-1].symbol==symbol){returnsuffix;}node=_nodes[node].quick_link;}}node_idfront_appendable(intsymbol,node_idnode)const{intn=int(_text.size());while(true){intlength=_nodes[node].length;if(length==-1||(length<n&&_text[length].symbol==symbol)){returnnode;}node_idsuffix=_nodes[node].suffix_link;intsuffix_length=_nodes[suffix].length;if(suffix_length==-1||_text[suffix_length].symbol==symbol){returnsuffix;}node=_nodes[node].quick_link;}}node_idprefix_node()const{return_text.empty()?even_root:_text.front().prefix_surface;}node_idsuffix_node()const{return_text.empty()?even_root:_text.back().suffix_surface;}voidinitialize_roots(){_nodes.clear();_nodes.emplace_back(-1,odd_root,odd_root,odd_root);_nodes.emplace_back(0,odd_root,odd_root,odd_root);_distinct_palindromes=0;}public:DequeEertree(){initialize_roots();}template<classSequence>explicitDequeEertree(constSequence&sequence){initialize_roots();build(sequence);}intsize()const{return_distinct_palindromes;}inttext_length()const{returnint(_text.size());}boolempty()const{return_text.empty();}intdistinct_palindrome_count()const{return_distinct_palindromes;}intlongest_prefix_length()const{return_nodes[prefix_node()].length;}intlongest_suffix_length()const{return_nodes[suffix_node()].length;}voidreserve(std::size_toperation_capacity){_nodes.reserve(operation_capacity+2);}voidclear(){_text.clear();initialize_roots();}template<classSymbol>voidpush_back(constSymbol&value){intsymbol=symbol_index(value);node_idparent=_text.empty()?odd_root:back_appendable(symbol,suffix_node());node_idpalindrome=_nodes[parent].next[symbol];node_idsuffix=even_root;if(palindrome==null_node){if(parent!=odd_root){node_idsuffix_parent=back_appendable(symbol,_nodes[parent].suffix_link);suffix=_nodes[suffix_parent].next[symbol];assert(suffix!=null_node);}}else{suffix=_nodes[palindrome].suffix_link;}_text.push_back(Position{symbol,even_root,even_root});intn=int(_text.size());if(palindrome==null_node){palindrome=new_node(parent,suffix,_nodes[parent].length+2,symbol);Node&created=_nodes[palindrome];if(_nodes[suffix].suffix_link!=odd_root&&_text[n-_nodes[suffix].length-1].symbol==_text[n-_nodes[_nodes[suffix].suffix_link].length-1].symbol){created.quick_link=_nodes[suffix].quick_link;}else{created.quick_link=_nodes[suffix].suffix_link;}}intleft=n-_nodes[palindrome].length;_text.back().suffix_surface=palindrome;_text[left].prefix_surface=palindrome;if(_nodes[suffix].length>=1&&_text[left+_nodes[suffix].length-1].suffix_surface==suffix){_text[left+_nodes[suffix].length-1].suffix_surface=even_root;}_nodes[palindrome].surface_count++;}template<classSymbol>voidpush_front(constSymbol&value){intsymbol=symbol_index(value);node_idparent=_text.empty()?odd_root:front_appendable(symbol,prefix_node());node_idpalindrome=_nodes[parent].next[symbol];node_idsuffix=even_root;if(palindrome==null_node){if(parent!=odd_root){node_idsuffix_parent=front_appendable(symbol,_nodes[parent].suffix_link);suffix=_nodes[suffix_parent].next[symbol];assert(suffix!=null_node);}}else{suffix=_nodes[palindrome].suffix_link;}_text.push_front(Position{symbol,even_root,even_root});if(palindrome==null_node){palindrome=new_node(parent,suffix,_nodes[parent].length+2,symbol);Node&created=_nodes[palindrome];if(_nodes[suffix].suffix_link!=odd_root&&_text[_nodes[suffix].length].symbol==_text[_nodes[_nodes[suffix].suffix_link].length].symbol){created.quick_link=_nodes[suffix].quick_link;}else{created.quick_link=_nodes[suffix].suffix_link;}}_text.front().prefix_surface=palindrome;_text[_nodes[palindrome].length-1].suffix_surface=palindrome;if(_nodes[suffix].length>=1&&_text[_nodes[palindrome].length-_nodes[suffix].length].prefix_surface==suffix){_text[_nodes[palindrome].length-_nodes[suffix].length].prefix_surface=even_root;}_nodes[palindrome].surface_count++;}voidpop_back(){assert(!_text.empty());node_idpalindrome=suffix_node();node_idsuffix=_nodes[palindrome].suffix_link;intleft=text_length()-_nodes[palindrome].length;intsuffix_end=left+_nodes[suffix].length-1;if(_nodes[palindrome].length>=2&&_nodes[_text[suffix_end].suffix_surface].length<_nodes[suffix].length){_text[suffix_end].suffix_surface=suffix;_text[left].prefix_surface=suffix;}else{_text[left].prefix_surface=even_root;}_nodes[palindrome].surface_count--;intsymbol=_text.back().symbol;if(_nodes[palindrome].surface_count==0&&_nodes[palindrome].suffix_link_children==0){remove_node(palindrome,symbol);}_text.pop_back();}voidpop_front(){assert(!_text.empty());node_idpalindrome=prefix_node();node_idsuffix=_nodes[palindrome].suffix_link;intsuffix_start=_nodes[palindrome].length-_nodes[suffix].length;if(_nodes[palindrome].length>=2&&_nodes[_text[suffix_start].prefix_surface].length<_nodes[suffix].length){_text[suffix_start].prefix_surface=suffix;_text[_nodes[palindrome].length-1].suffix_surface=suffix;}else{_text[_nodes[palindrome].length-1].suffix_surface=even_root;}_nodes[palindrome].surface_count--;intsymbol=_text.front().symbol;if(_nodes[palindrome].surface_count==0&&_nodes[palindrome].suffix_link_children==0){remove_node(palindrome,symbol);}_text.pop_front();}template<classSequence>voidbuild(constSequence&sequence){for(constauto&symbol:sequence)push_back(symbol);}};template<intAlphabetSize=26,intFirstCharacter='a'>usingDoubleEndedEertree=DequeEertree<AlphabetSize,FirstCharacter>;template<intAlphabetSize=26,intFirstCharacter='a'>usingDequePalindromicTree=DequeEertree<AlphabetSize,FirstCharacter>;}// namespace string}// namespace m1une#line 1 "string/eertree.hpp"
#line 8 "string/eertree.hpp"
#include<utility>
#line 10 "string/eertree.hpp"
namespacem1une{namespacestring{template<intAlphabetSize=26,intFirstCharacter='a'>structEertree{static_assert(0<AlphabetSize);usingnode_id=int;staticconstexprnode_ideven_root=0;staticconstexprnode_idodd_root=1;staticconstexprnode_idnull_node=-1;structNode{std::array<node_id,AlphabetSize>next;node_idsuffix_link;node_idseries_link;intlength;intdiff;intsuffix_count;intfirst_end;longlongsuffix_occurrences;Node(intlength_value=0,node_idsuffix_link_value=even_root,node_idseries_link_value=even_root):suffix_link(suffix_link_value),series_link(series_link_value),length(length_value),diff(0),suffix_count(0),first_end(0),suffix_occurrences(0){next.fill(null_node);}};private:std::vector<Node>_nodes;std::vector<int>_text;std::vector<node_id>_longest_suffix;node_id_last;template<classSymbol>staticintsymbol_index(constSymbol&symbol){intindex=int(symbol)-FirstCharacter;assert(0<=index&&index<AlphabetSize);returnindex;}node_idfind_extendable(node_idnode,intposition,intsymbol)const{while(true){intlength=_nodes[node].length;intleft=position-length-1;if(0<=left&&_text[left]==symbol)returnnode;node=_nodes[node].suffix_link;}}node_idnew_node(intlength){assert(_nodes.size()<std::size_t(std::numeric_limits<int>::max()));_nodes.emplace_back(length);returnint(_nodes.size())-1;}public:Eertree(){clear();}template<classSequence>explicitEertree(constSequence&sequence){clear();build(sequence);}intsize()const{returnint(_nodes.size())-2;}boolempty()const{returnsize()==0;}intnode_count()const{returnint(_nodes.size());}inttext_length()const{returnint(_text.size());}node_idlast()const{return_last;}intlongest_suffix_length()const{return_nodes[_last].length;}constNode&node(node_idid)const{assert(0<=id&&id<node_count());return_nodes[id];}conststd::vector<Node>&nodes()const{return_nodes;}node_idlongest_suffix_node(intprefix_length)const{assert(1<=prefix_length&&prefix_length<=text_length());return_longest_suffix[prefix_length-1];}conststd::vector<node_id>&longest_suffix_nodes()const{return_longest_suffix;}template<classCallback>voidfor_each_suffix(node_idid,Callbackcallback)const{assert(0<=id&&id<node_count());while(id>=2){callback(id);id=_nodes[id].suffix_link;}}template<classCallback>voidfor_each_suffix(Callbackcallback)const{for_each_suffix(_last,callback);}voidreserve(std::size_ttext_capacity){_text.reserve(text_capacity);_longest_suffix.reserve(text_capacity);_nodes.reserve(text_capacity+2);}voidclear(){_nodes.clear();_nodes.emplace_back(0,odd_root,even_root);_nodes.emplace_back(-1,odd_root,odd_root);_text.clear();_longest_suffix.clear();_last=even_root;}template<classSymbol>node_idadd(constSymbol&value){intsymbol=symbol_index(value);intposition=int(_text.size());_text.push_back(symbol);node_idcurrent=find_extendable(_last,position,symbol);node_idnext=_nodes[current].next[symbol];if(next==null_node){intlength=_nodes[current].length+2;next=new_node(length);_nodes[current].next[symbol]=next;node_idsuffix_link=even_root;if(length!=1){node_idcandidate=find_extendable(_nodes[current].suffix_link,position,symbol);suffix_link=_nodes[candidate].next[symbol];assert(suffix_link!=null_node);}Node&created=_nodes[next];created.suffix_link=suffix_link;created.diff=created.length-_nodes[suffix_link].length;created.series_link=created.diff==_nodes[suffix_link].diff?_nodes[suffix_link].series_link:suffix_link;created.suffix_count=_nodes[suffix_link].suffix_count+1;created.first_end=position+1;}_last=next;_nodes[_last].suffix_occurrences++;_longest_suffix.push_back(_last);return_last;}template<classSequence>voidbuild(constSequence&sequence){for(constauto&symbol:sequence)add(symbol);}std::vector<longlong>occurrence_counts()const{std::vector<longlong>result(_nodes.size(),0);for(node_idid=0;id<node_count();id++){result[id]=_nodes[id].suffix_occurrences;}for(node_idid=node_count()-1;id>=2;id--){result[_nodes[id].suffix_link]+=result[id];}returnresult;}std::pair<int,int>first_occurrence(node_idid)const{assert(2<=id&&id<node_count());intend=_nodes[id].first_end;return{end-_nodes[id].length,end};}};template<intAlphabetSize=26,intFirstCharacter='a'>usingPalindromicTree=Eertree<AlphabetSize,FirstCharacter>;}// namespace string}// namespace m1une#line 1 "string/kmp.hpp"
#line 5 "string/kmp.hpp"
namespacem1une{namespacestring{// Returns the KMP prefix function.template<classSequence>std::vector<int>prefix_function(constSequence&sequence){intn=int(sequence.size());std::vector<int>prefix(n);for(inti=1;i<n;i++){intj=prefix[i-1];while(j>0&&sequence[i]!=sequence[j]){j=prefix[j-1];}if(sequence[i]==sequence[j])j++;prefix[i]=j;}returnprefix;}// Returns every starting position where pattern occurs in text.// An empty pattern occurs at every position from 0 through text.size().template<classText,classPattern>std::vector<int>kmp_search(constText&text,constPattern&pattern){intn=int(text.size());intm=int(pattern.size());if(m==0){std::vector<int>occurrences(n+1);for(inti=0;i<=n;i++)occurrences[i]=i;returnoccurrences;}std::vector<int>prefix=prefix_function(pattern);std::vector<int>occurrences;intmatched=0;for(inti=0;i<n;i++){while(matched>0&&text[i]!=pattern[matched]){matched=prefix[matched-1];}if(text[i]==pattern[matched])matched++;if(matched==m){occurrences.push_back(i-m+1);matched=prefix[matched-1];}}returnoccurrences;}}// namespace string}// namespace m1une#line 1 "string/levenshtein_distance.hpp"
#include<algorithm>
#line 7 "string/levenshtein_distance.hpp"
namespacem1une{namespacestring{namespacelevenshtein_distance_detail{template<classRowSequence,classColumnSequence>intsolve(constRowSequence&rows,constColumnSequence&columns){introw_count=int(rows.size());intcolumn_count=int(columns.size());std::vector<int>distance(column_count+1);for(intcolumn=0;column<=column_count;column++)distance[column]=column;for(introw=1;row<=row_count;row++){intdiagonal=distance[0];distance[0]=row;for(intcolumn=1;column<=column_count;column++){intabove=distance[column];intsubstitution=diagonal+(rows[row-1]==columns[column-1]?0:1);distance[column]=std::min({above+1,distance[column-1]+1,substitution});diagonal=above;}}returndistance[column_count];}template<classRowSequence,classColumnSequence>intsolve_bounded(constRowSequence&rows,constColumnSequence&columns,intmax_distance){introw_count=int(rows.size());intcolumn_count=int(columns.size());assert(column_count<=row_count);if(row_count-column_count>max_distance)returnmax_distance+1;if(max_distance>=row_count)returnsolve(rows,columns);intinfinity=max_distance+1;intprevious_left=0;intprevious_right=std::min(column_count,max_distance);std::vector<int>previous(previous_right+1);for(intcolumn=0;column<=previous_right;column++)previous[column]=column;std::vector<int>current;for(introw=1;row<=row_count;row++){intcurrent_left=std::max(0,row-max_distance);intcurrent_right=int(std::min<longlong>(column_count,static_cast<longlong>(row)+max_distance));current.assign(current_right-current_left+1,infinity);for(intcolumn=current_left;column<=current_right;column++){intbest=infinity;if(previous_left<=column&&column<=previous_right){best=std::min(best,previous[column-previous_left]+1);}if(current_left<column){best=std::min(best,current[column-current_left-1]+1);}if(0<column&&previous_left<=column-1&&column-1<=previous_right){intsubstitution=previous[column-1-previous_left]+(rows[row-1]==columns[column-1]?0:1);best=std::min(best,substitution);}current[column-current_left]=std::min(best,infinity);}previous.swap(current);previous_left=current_left;previous_right=current_right;}returnprevious[column_count-previous_left];}}// namespace levenshtein_distance_detail// Returns the minimum number of insertions, deletions, and substitutions// needed to transform first into second.template<classSequence1,classSequence2>intlevenshtein_distance(constSequence1&first,constSequence2&second){if(first.size()<second.size()){returnlevenshtein_distance_detail::solve(second,first);}returnlevenshtein_distance_detail::solve(first,second);}// Returns the exact distance when it is at most max_distance, and// max_distance + 1 otherwise.template<classSequence1,classSequence2>intlevenshtein_distance(constSequence1&first,constSequence2&second,intmax_distance){assert(0<=max_distance);if(first.size()<second.size()){returnlevenshtein_distance_detail::solve_bounded(second,first,max_distance);}returnlevenshtein_distance_detail::solve_bounded(first,second,max_distance);}}// namespace string}// namespace m1une#line 1 "string/longest_common_extension.hpp"
#line 6 "string/longest_common_extension.hpp"
#include<string>
#line 9 "string/longest_common_extension.hpp"
#line 1 "string/suffix_array.hpp"
#line 6 "string/suffix_array.hpp"
#include<numeric>
#line 8 "string/suffix_array.hpp"
#include<type_traits>
#line 10 "string/suffix_array.hpp"
namespacem1une{namespacestring{namespacedetail{template<classSequence>std::vector<int>suffix_array_impl(constSequence&sequence){intn=int(sequence.size());if(n==0)return{};usingValue=std::remove_cv_t<std::remove_reference_t<decltype(sequence[0])>>;std::vector<Value>sorted(sequence.begin(),sequence.end());std::sort(sorted.begin(),sorted.end());sorted.erase(std::unique(sorted.begin(),sorted.end()),sorted.end());intlength=n+1;std::vector<int>order(length);std::vector<int>rank(length);std::vector<int>key(length);key[n]=0;for(inti=0;i<n;i++){key[i]=int(std::lower_bound(sorted.begin(),sorted.end(),sequence[i])-sorted.begin())+1;}intalphabet=int(sorted.size())+1;std::vector<int>count(std::max(length,alphabet),0);for(intvalue:key)count[value]++;for(inti=1;i<alphabet;i++)count[i]+=count[i-1];for(inti=length-1;i>=0;i--)order[--count[key[i]]]=i;intclasses=1;rank[order[0]]=0;for(inti=1;i<length;i++){if(key[order[i-1]]!=key[order[i]])classes++;rank[order[i]]=classes-1;}std::vector<int>shifted(length);std::vector<int>next_rank(length);for(longlonghalf=1;half<length;half<<=1){for(inti=0;i<length;i++){longlongposition=order[i]-half;if(position<0)position+=length;shifted[i]=int(position);}count.assign(classes,0);for(intposition:shifted)count[rank[position]]++;for(inti=1;i<classes;i++)count[i]+=count[i-1];for(inti=length-1;i>=0;i--){intposition=shifted[i];order[--count[rank[position]]]=position;}intnext_classes=1;next_rank[order[0]]=0;for(inti=1;i<length;i++){intcurrent=order[i];intprevious=order[i-1];intcurrent_second=int((current+half)%length);intprevious_second=int((previous+half)%length);if(rank[current]!=rank[previous]||rank[current_second]!=rank[previous_second]){next_classes++;}next_rank[current]=next_classes-1;}rank.swap(next_rank);classes=next_classes;if(classes==length)break;}std::vector<int>suffixes(n);for(inti=0;i<n;i++)suffixes[i]=order[i+1];returnsuffixes;}}// namespace detailtemplate<classSequence>std::vector<int>suffix_array(constSequence&sequence){returndetail::suffix_array_impl(sequence);}inlinestd::vector<int>suffix_array(conststd::string&text){std::vector<unsignedchar>values;values.reserve(text.size());for(unsignedcharcharacter:text)values.push_back(character);returndetail::suffix_array_impl(values);}template<classSequence>std::vector<int>lcp_array(constSequence&sequence,conststd::vector<int>&suffixes){intn=int(sequence.size());assert(int(suffixes.size())==n);if(n==0)return{};std::vector<int>rank(n);for(inti=0;i<n;i++){assert(0<=suffixes[i]&&suffixes[i]<n);rank[suffixes[i]]=i;}std::vector<int>lcp(n-1);intcommon=0;for(inti=0;i<n;i++){intposition=rank[i];if(position==n-1){common=0;continue;}intj=suffixes[position+1];while(i+common<n&&j+common<n&&sequence[i+common]==sequence[j+common]){common++;}lcp[position]=common;if(common>0)common--;}returnlcp;}}// namespace string}// namespace m1une#line 11 "string/longest_common_extension.hpp"
namespacem1une{namespacestring{template<classSequence=std::string>structLongestCommonExtension{private:Sequence_sequence;std::vector<int>_suffix_array;std::vector<int>_rank;std::vector<int>_lcp;std::vector<int>_log;std::vector<std::vector<int>>_table;intrange_min(intleft,intright)const{assert(0<=left&&left<right&&right<=int(_lcp.size()));intk=_log[right-left];returnstd::min(_table[k][left],_table[k][right-(1<<k)]);}voidbuild(){intn=int(_sequence.size());_suffix_array=m1une::string::suffix_array(_sequence);_rank.assign(n,0);for(inti=0;i<n;i++){_rank[_suffix_array[i]]=i;}_lcp=m1une::string::lcp_array(_sequence,_suffix_array);intm=int(_lcp.size());_log.assign(m+1,0);for(inti=2;i<=m;i++){_log[i]=_log[i>>1]+1;}_table.clear();if(m==0)return;_table.assign(_log[m]+1,std::vector<int>());_table[0]=_lcp;for(intk=1;k<int(_table.size());k++){intwidth=1<<k;inthalf=width>>1;_table[k].resize(m-width+1);for(inti=0;i+width<=m;i++){_table[k][i]=std::min(_table[k-1][i],_table[k-1][i+half]);}}}public:LongestCommonExtension()=default;explicitLongestCommonExtension(constSequence&sequence):_sequence(sequence){build();}explicitLongestCommonExtension(Sequence&&sequence):_sequence(std::move(sequence)){build();}intsize()const{returnint(_sequence.size());}boolempty()const{return_sequence.empty();}constSequence&sequence()const{return_sequence;}conststd::vector<int>&suffix_array()const{return_suffix_array;}conststd::vector<int>&rank()const{return_rank;}conststd::vector<int>&lcp_array()const{return_lcp;}intlongest_common_extension(inti,intj)const{intn=size();assert(0<=i&&i<=n);assert(0<=j&&j<=n);if(i==j)returnn-i;if(i==n||j==n)return0;intleft=_rank[i];intright=_rank[j];if(left>right)std::swap(left,right);returnrange_min(left,right);}intlongest_common_extension(inti,intj,intlimit)const{assert(0<=limit);returnstd::min(longest_common_extension(i,j),limit);}intlcp(inti,intj)const{returnlongest_common_extension(i,j);}intoperator()(inti,intj)const{returnlongest_common_extension(i,j);}intcompare_suffix(inti,intj)const{intn=size();assert(0<=i&&i<=n);assert(0<=j&&j<=n);if(i==j)return0;intcommon=longest_common_extension(i,j);if(i+common==n&&j+common==n)return0;if(i+common==n)return-1;if(j+common==n)return1;return_sequence[i+common]<_sequence[j+common]?-1:1;}intcompare(intl1,intr1,intl2,intr2)const{intn=size();assert(0<=l1&&l1<=r1&&r1<=n);assert(0<=l2&&l2<=r2&&r2<=n);intlen1=r1-l1;intlen2=r2-l2;intcommon=longest_common_extension(l1,l2,std::min(len1,len2));if(common==len1&&common==len2)return0;if(common==len1)return-1;if(common==len2)return1;return_sequence[l1+common]<_sequence[l2+common]?-1:1;}};}// namespace string}// namespace m1une#line 1 "string/longest_common_subsequence.hpp"
#line 9 "string/longest_common_subsequence.hpp"
namespacem1une{namespacestring{structLongestCommonSubsequence{std::vector<std::pair<int,int>>matches;intlength()const{returnint(matches.size());}boolempty()const{returnmatches.empty();}std::vector<int>first_indices()const{std::vector<int>result;result.reserve(matches.size());for(auto[i,j]:matches){(void)j;result.push_back(i);}returnresult;}std::vector<int>second_indices()const{std::vector<int>result;result.reserve(matches.size());for(auto[i,j]:matches){(void)i;result.push_back(j);}returnresult;}template<classSequence>std::vector<std::remove_cv_t<std::remove_reference_t<decltype(std::declval<constSequence&>()[0])>>>values_from_first(constSequence&first)const{usingValue=std::remove_cv_t<std::remove_reference_t<decltype(std::declval<constSequence&>()[0])>>;std::vector<Value>result;result.reserve(matches.size());for(auto[i,j]:matches){(void)j;result.push_back(first[i]);}returnresult;}template<classSequence>std::vector<std::remove_cv_t<std::remove_reference_t<decltype(std::declval<constSequence&>()[0])>>>values_from_second(constSequence&second)const{usingValue=std::remove_cv_t<std::remove_reference_t<decltype(std::declval<constSequence&>()[0])>>;std::vector<Value>result;result.reserve(matches.size());for(auto[i,j]:matches){(void)i;result.push_back(second[j]);}returnresult;}};template<classFirstSequence,classSecondSequence>intlongest_common_subsequence_length(constFirstSequence&first,constSecondSequence&second){intn=int(first.size());intm=int(second.size());if(m<=n){std::vector<int>dp(m+1,0);for(inti=0;i<n;i++){intdiagonal=0;for(intj=0;j<m;j++){intup=dp[j+1];if(first[i]==second[j]){dp[j+1]=diagonal+1;}else{dp[j+1]=std::max(dp[j+1],dp[j]);}diagonal=up;}}returndp[m];}else{std::vector<int>dp(n+1,0);for(intj=0;j<m;j++){intdiagonal=0;for(inti=0;i<n;i++){intup=dp[i+1];if(first[i]==second[j]){dp[i+1]=diagonal+1;}else{dp[i+1]=std::max(dp[i+1],dp[i]);}diagonal=up;}}returndp[n];}}template<classFirstSequence,classSecondSequence>LongestCommonSubsequencelongest_common_subsequence(constFirstSequence&first,constSecondSequence&second){intn=int(first.size());intm=int(second.size());std::vector<std::vector<int>>dp(n+1,std::vector<int>(m+1,0));for(inti=0;i<n;i++){for(intj=0;j<m;j++){if(first[i]==second[j]){dp[i+1][j+1]=dp[i][j]+1;}else{dp[i+1][j+1]=std::max(dp[i][j+1],dp[i+1][j]);}}}LongestCommonSubsequenceresult;result.matches.reserve(dp[n][m]);inti=n;intj=m;while(i>0&&j>0){if(first[i-1]==second[j-1]){result.matches.emplace_back(i-1,j-1);i--;j--;}elseif(dp[i-1][j]>=dp[i][j-1]){i--;}else{j--;}}std::reverse(result.matches.begin(),result.matches.end());returnresult;}}// namespace string}// namespace m1une#line 1 "string/longest_common_substring.hpp"
#line 9 "string/longest_common_substring.hpp"
#line 11 "string/longest_common_substring.hpp"
namespacem1une{namespacestring{structLongestCommonSubstring{intfirst_left=0;intfirst_right=0;intsecond_left=0;intsecond_right=0;intlength()const{assert(first_right-first_left==second_right-second_left);returnfirst_right-first_left;}boolempty()const{returnlength()==0;}std::pair<int,int>first_interval()const{return{first_left,first_right};}std::pair<int,int>second_interval()const{return{second_left,second_right};}};namespacedetail{template<classSequence>std::vector<int>compressed_join_with_separator(constSequence&first,constSequence&second){usingValue=std::remove_cv_t<std::remove_reference_t<decltype(first[0])>>;std::vector<Value>values;values.reserve(first.size()+second.size());for(constauto&value:first)values.push_back(value);for(constauto&value:second)values.push_back(value);std::sort(values.begin(),values.end());values.erase(std::unique(values.begin(),values.end()),values.end());std::vector<int>joined;joined.reserve(first.size()+second.size()+1);for(constauto&value:first){joined.push_back(int(std::lower_bound(values.begin(),values.end(),value)-values.begin())+2);}joined.push_back(1);for(constauto&value:second){joined.push_back(int(std::lower_bound(values.begin(),values.end(),value)-values.begin())+2);}returnjoined;}}// namespace detailtemplate<classSequence>LongestCommonSubstringlongest_common_substring(constSequence&first,constSequence&second){intn=int(first.size());intm=int(second.size());std::vector<int>joined=detail::compressed_join_with_separator(first,second);std::vector<int>suffixes=suffix_array(joined);std::vector<int>lcp=lcp_array(joined,suffixes);LongestCommonSubstringresult;for(inti=0;i+1<int(suffixes.size());i++){inta=suffixes[i];intb=suffixes[i+1];if(a==n||b==n)continue;boola_first=a<n;boolb_first=b<n;if(a_first==b_first)continue;intfirst_left=a_first?a:b;intsecond_left=a_first?b-n-1:a-n-1;intlength=lcp[i];length=std::min(length,n-first_left);length=std::min(length,m-second_left);if(length>result.length()){result.first_left=first_left;result.first_right=first_left+length;result.second_left=second_left;result.second_right=second_left+length;}}returnresult;}}// namespace string}// namespace m1une#line 1 "string/lyndon_factorization.hpp"
#line 6 "string/lyndon_factorization.hpp"
#line 1 "string/minimum_rotation.hpp"
namespacem1une{namespacestring{// Returns the smallest starting index of a lexicographically minimum cyclic shift.template<classSequence>intminimum_cyclic_shift(constSequence&sequence){constintsize=int(sequence.size());if(size==0)return0;autoless=[&](intleft,intright){returnsequence[left<size?left:left-size]<sequence[right<size?right:right-size];};intanswer=0;intstart=0;while(start<size){answer=start;intscan=start+1;intmatched=start;while(scan<2*size&&!less(scan,matched)){if(less(matched,scan)){matched=start;}else{matched++;}scan++;}constintperiod=scan-matched;while(start<=matched)start+=period;}returnanswer;}}// namespace string}// namespace m1une#line 8 "string/lyndon_factorization.hpp"
namespacem1une{namespacestring{// Returns boundaries 0 = a[0] < a[1] < ... < a[k] = sequence.size()// of the Lyndon factorization.template<classSequence>std::vector<int>lyndon_factor_boundaries(constSequence&sequence){intn=int(sequence.size());std::vector<int>boundaries;boundaries.push_back(0);inti=0;while(i<n){intj=i+1;intk=i;while(j<n&&!(sequence[j]<sequence[k])){if(sequence[k]<sequence[j]){k=i;}else{k++;}j++;}intlength=j-k;while(i<=k){i+=length;boundaries.push_back(i);}}returnboundaries;}// Returns half-open intervals [left, right) of the Lyndon factorization.template<classSequence>std::vector<std::pair<int,int>>lyndon_factorization(constSequence&sequence){std::vector<int>boundaries=lyndon_factor_boundaries(sequence);std::vector<std::pair<int,int>>factors;factors.reserve(boundaries.size()-1);for(inti=0;i+1<int(boundaries.size());i++){factors.emplace_back(boundaries[i],boundaries[i+1]);}returnfactors;}}// namespace string}// namespace m1une#line 1 "string/manacher.hpp"
#line 7 "string/manacher.hpp"
namespacem1une{namespacestring{structManacherResult{// odd[i] is the radius including center i.// The palindrome is [i - odd[i] + 1, i + odd[i]).std::vector<int>odd;// even[i] is the radius centered between i - 1 and i.// The palindrome is [i - even[i], i + even[i]).std::vector<int>even;intsize()const{returnint(odd.size());}boolempty()const{returnodd.empty();}boolis_palindrome(intleft,intright)const{intn=size();assert(0<=left&&left<=right&&right<=n);intlength=right-left;if(length==0)returntrue;if(length&1){intcenter=(left+right)/2;returnlength/2+1<=odd[center];}intcenter=(left+right)/2;returnlength/2<=even[center];}intlongest_length()const{intresult=0;for(intradius:odd)result=std::max(result,2*radius-1);for(intradius:even)result=std::max(result,2*radius);returnresult;}};template<classSequence>ManacherResultmanacher(constSequence&sequence){intn=int(sequence.size());ManacherResultresult;result.odd.assign(n,0);result.even.assign(n,0);intleft=0;intright=-1;for(inti=0;i<n;i++){intradius=i>right?1:std::min(result.odd[left+right-i],right-i+1);while(0<=i-radius&&i+radius<n&&sequence[i-radius]==sequence[i+radius]){radius++;}result.odd[i]=radius;if(right<i+radius-1){left=i-radius+1;right=i+radius-1;}}left=0;right=-1;for(inti=0;i<n;i++){intradius=i>right?0:std::min(result.even[left+right-i+1],right-i+1);while(0<=i-radius-1&&i+radius<n&&sequence[i-radius-1]==sequence[i+radius]){radius++;}result.even[i]=radius;if(right<i+radius-1){left=i-radius;right=i+radius-1;}}returnresult;}}// namespace string}// namespace m1une#line 1 "string/map_trie.hpp"
#line 6 "string/map_trie.hpp"
#include<functional>
#line 8 "string/map_trie.hpp"
#include<map>
#line 10 "string/map_trie.hpp"
namespacem1une{namespacestring{// A multiset trie whose outgoing edges are stored in ordered maps.template<classSymbol,classCompare=std::less<Symbol>>structMapTrie{usingnode_id=int;staticconstexprnode_idnull_node=-1;structNode{std::map<Symbol,node_id,Compare>child;intsubtree_count=0;intterminal_count=0;};private:std::vector<Node>_nodes;int_distinct_size;node_idnew_node(){assert(_nodes.size()<std::size_t(std::numeric_limits<int>::max()));_nodes.emplace_back();returnint(_nodes.size())-1;}template<classSequence>node_idfind_node(constSequence&sequence)const{node_idnode=0;for(constauto&symbol:sequence){autoiterator=_nodes[node].child.find(symbol);if(iterator==_nodes[node].child.end())returnnull_node;node=iterator->second;if(_nodes[node].subtree_count==0)returnnull_node;}returnnode;}public:MapTrie():_nodes(1),_distinct_size(0){}intsize()const{return_nodes[0].subtree_count;}intdistinct_size()const{return_distinct_size;}boolempty()const{returnsize()==0;}node_idroot()const{return0;}constNode&node(node_idid)const{assert(0<=id&&std::size_t(id)<_nodes.size());return_nodes[id];}template<classSequence>node_idfind(constSequence&sequence)const{returnfind_node(sequence);}std::size_tnode_count()const{return_nodes.size();}voidreserve(std::size_tnode_capacity){_nodes.reserve(node_capacity);}voidclear(){_nodes.clear();_nodes.emplace_back();_distinct_size=0;}template<classSequence>node_idinsert(constSequence&sequence,intmultiplicity=1){assert(0<multiplicity);node_idnode=0;_nodes[node].subtree_count+=multiplicity;for(constauto&symbol:sequence){autoiterator=_nodes[node].child.find(symbol);node_idchild;if(iterator==_nodes[node].child.end()){child=new_node();_nodes[node].child.emplace(symbol,child);}else{child=iterator->second;}node=child;_nodes[node].subtree_count+=multiplicity;}if(_nodes[node].terminal_count==0)_distinct_size++;_nodes[node].terminal_count+=multiplicity;returnnode;}template<classSequence>intcount(constSequence&sequence)const{node_idnode=find_node(sequence);returnnode==null_node?0:_nodes[node].terminal_count;}template<classSequence>boolcontains(constSequence&sequence)const{returncount(sequence)!=0;}// Returns the number of stored sequences beginning with prefix.template<classSequence>intprefix_count(constSequence&prefix)const{node_idnode=find_node(prefix);returnnode==null_node?0:_nodes[node].subtree_count;}template<classSequence>boolstarts_with(constSequence&prefix)const{returnprefix_count(prefix)!=0;}template<classSequence>boolerase_one(constSequence&sequence){node_idterminal=find_node(sequence);if(terminal==null_node||_nodes[terminal].terminal_count==0){returnfalse;}node_idnode=0;_nodes[node].subtree_count--;for(constauto&symbol:sequence){node=_nodes[node].child.find(symbol)->second;_nodes[node].subtree_count--;}_nodes[node].terminal_count--;if(_nodes[node].terminal_count==0)_distinct_size--;returntrue;}template<classSequence>boolerase(constSequence&sequence){returnerase_one(sequence);}template<classSequence>interase_all(constSequence&sequence){intmultiplicity=count(sequence);if(multiplicity==0)return0;node_idnode=0;_nodes[node].subtree_count-=multiplicity;for(constauto&symbol:sequence){node=_nodes[node].child.find(symbol)->second;_nodes[node].subtree_count-=multiplicity;}_nodes[node].terminal_count=0;_distinct_size--;returnmultiplicity;}// Calls callback(length, multiplicity) for every stored prefix.// The empty prefix is reported with length 0 when it is stored.template<classSequence,classCallback>voidfor_each_prefix(constSequence&sequence,Callbackcallback)const{node_idnode=0;if(_nodes[node].terminal_count!=0){callback(0,_nodes[node].terminal_count);}intlength=0;for(constauto&symbol:sequence){autoiterator=_nodes[node].child.find(symbol);if(iterator==_nodes[node].child.end())return;node=iterator->second;if(_nodes[node].subtree_count==0)return;length++;if(_nodes[node].terminal_count!=0){callback(length,_nodes[node].terminal_count);}}}// Returns the length of the longest stored sequence that is a prefix.// Returns -1 when no stored prefix exists.template<classSequence>intlongest_prefix(constSequence&sequence)const{intresult=_nodes[0].terminal_count==0?-1:0;for_each_prefix(sequence,[&result](intlength,int){result=length;});returnresult;}};}// namespace string}// namespace m1une#line 1 "string/palindrome_lexicographical_order.hpp"
#line 9 "string/palindrome_lexicographical_order.hpp"
#line 12 "string/palindrome_lexicographical_order.hpp"
namespacem1une{namespacestring{// Indexes the distinct nonempty palindromic substrings of one sequence.template<classSequence=std::string,intAlphabetSize=26,intFirstCharacter='a'>structPalindromeLexicographicalOrder{static_assert(0<AlphabetSize);usingeertree_type=Eertree<AlphabetSize,FirstCharacter>;usingnode_id=typenameeertree_type::node_id;private:Sequence_sequence;eertree_type_eertree;std::vector<node_id>_nodes_in_order;std::vector<int>_order_of_node;template<classSymbol>staticintsymbol_index(constSymbol&symbol){intindex=int(symbol)-FirstCharacter;assert(0<=index&&index<AlphabetSize);returnindex;}voidbuild_order(){constintnode_count=_eertree.node_count();std::vector<std::vector<node_id>>suffix_children(node_count);for(node_idid=0;id<node_count;id++){if(id==eertree_type::odd_root)continue;suffix_children[_eertree.node(id).suffix_link].push_back(id);}std::vector<int>enter(node_count);std::vector<int>leave(node_count);std::vector<std::pair<node_id,bool>>stack;stack.reserve(2*node_count);stack.emplace_back(eertree_type::odd_root,false);inttimer=0;while(!stack.empty()){auto[id,exiting]=stack.back();stack.pop_back();if(exiting){leave[id]=timer;continue;}enter[id]=timer++;stack.emplace_back(id,true);constauto&children=suffix_children[id];for(inti=int(children.size())-1;i>=0;i--){stack.emplace_back(children[i],false);}}std::vector<int>suffixes=suffix_array(_sequence);std::vector<int>suffix_rank(_sequence.size());for(intrank=0;rank<int(suffixes.size());rank++){suffix_rank[suffixes[rank]]=rank;}_nodes_in_order.resize(_eertree.size());for(inti=0;i<_eertree.size();i++){_nodes_in_order[i]=i+2;}autois_ancestor=[&](node_idancestor,node_iddescendant){returnenter[ancestor]<=enter[descendant]&&leave[descendant]<=leave[ancestor];};std::sort(_nodes_in_order.begin(),_nodes_in_order.end(),[&](node_idfirst,node_idsecond){if(first==second)returnfalse;// A palindromic prefix is also a palindromic suffix, so prefix// cases are exactly the ancestor cases in the suffix-link tree.if(is_ancestor(first,second))returntrue;if(is_ancestor(second,first))returnfalse;// Otherwise the first mismatch occurs inside both substrings,// and the ranks of representative suffixes give their order.intfirst_start=_eertree.first_occurrence(first).first;intsecond_start=_eertree.first_occurrence(second).first;returnsuffix_rank[first_start]<suffix_rank[second_start];});_order_of_node.assign(node_count,-1);for(intorder=0;order<size();order++){_order_of_node[_nodes_in_order[order]]=order;}}public:PalindromeLexicographicalOrder():_order_of_node(2,-1){}explicitPalindromeLexicographicalOrder(constSequence&sequence):_sequence(sequence),_eertree(_sequence){build_order();}explicitPalindromeLexicographicalOrder(Sequence&&sequence):_sequence(std::move(sequence)),_eertree(_sequence){build_order();}intsize()const{returnint(_nodes_in_order.size());}boolempty()const{return_nodes_in_order.empty();}inttext_length()const{returnint(_sequence.size());}constSequence&sequence()const{return_sequence;}consteertree_type&eertree()const{return_eertree;}conststd::vector<node_id>&nodes_in_order()const{return_nodes_in_order;}intorder_of_node(node_idid)const{assert(2<=id&&id<_eertree.node_count());return_order_of_node[id];}node_idnode_by_order(intorder)const{assert(0<=order&&order<size());return_nodes_in_order[order];}template<classPalindrome>node_idfind(constPalindrome&palindrome)const{constintlength=int(palindrome.size());if(length==0)returneertree_type::null_node;for(inti=0;i<length/2;i++){if(palindrome[i]!=palindrome[length-1-i]){returneertree_type::null_node;}}node_idid=length&1?eertree_type::odd_root:eertree_type::even_root;for(inti=(length-1)/2;i>=0;i--){intsymbol=symbol_index(palindrome[i]);id=_eertree.node(id).next[symbol];if(id==eertree_type::null_node)returnid;}returnid;}template<classPalindrome>boolcontains(constPalindrome&palindrome)const{returnfind(palindrome)!=eertree_type::null_node;}template<classPalindrome>intorder_of_palindrome(constPalindrome&palindrome)const{node_idid=find(palindrome);returnid==eertree_type::null_node?-1:order_of_node(id);}std::pair<int,int>representative_occurrence(intorder)const{return_eertree.first_occurrence(node_by_order(order));}Sequencepalindrome(intorder)const{auto[left,right]=representative_occurrence(order);returnSequence(_sequence.begin()+left,_sequence.begin()+right);}Sequencekth(intorder)const{returnpalindrome(order);}};}// namespace string}// namespace m1une#line 1 "string/prefix_substring_lcs.hpp"
#line 9 "string/prefix_substring_lcs.hpp"
namespacem1une{namespacestring{// Answers LCS-length queries between a prefix of the first sequence and a// substring of the second sequence. Queries are evaluated as one offline batch.template<classFirstSequence,classSecondSequence>classPrefixSubstringLcs{private:structQuery{intfirst_prefix;intsecond_left;intsecond_right;};FirstSequence_first;SecondSequence_second;std::vector<Query>_queries;public:PrefixSubstringLcs(FirstSequencefirst,SecondSequencesecond):_first(std::move(first)),_second(std::move(second)){}intfirst_size()const{returnint(_first.size());}intsecond_size()const{returnint(_second.size());}intquery_count()const{returnint(_queries.size());}boolempty()const{return_queries.empty();}voidreserve(intquery_capacity){assert(0<=query_capacity);_queries.reserve(query_capacity);}voidclear(){_queries.clear();}// Adds LCS(first[0..first_prefix), second[second_left..second_right)) and// returns its insertion-order ID.intadd_query(intfirst_prefix,intsecond_left,intsecond_right){assert(0<=first_prefix&&first_prefix<=first_size());assert(0<=second_left&&second_left<=second_right);assert(second_right<=second_size());constintid=query_count();_queries.push_back(Query{first_prefix,second_left,second_right});returnid;}std::vector<int>calculate()const{constintfirst_length=first_size();constintsecond_length=second_size();constintcount=query_count();std::vector<int>answers(count,0);if(count==0||first_length==0||second_length==0){returnanswers;}std::vector<std::vector<int>>queries_by_prefix(first_length+1);for(intid=0;id<count;id++){constQuery&query=_queries[id];if(query.first_prefix>0&&query.second_left<query.second_right){queries_by_prefix[query.first_prefix].push_back(id);}}// seaweed[j] is the bottom endpoint of the seaweed entering at j for// the current prefix of the first sequence. -1 denotes the left edge.std::vector<int>seaweed(second_length);for(intj=0;j<second_length;j++)seaweed[j]=j;std::vector<int>heads(second_length+1,-1);std::vector<int>next(count,-1);std::vector<int>fenwick(second_length+1,0);for(inti=0;i<first_length;i++){intdisplaced=-1;for(intj=0;j<second_length;j++){if(_first[i]==_second[j]||seaweed[j]<displaced){std::swap(seaweed[j],displaced);}}conststd::vector<int>&prefix_queries=queries_by_prefix[i+1];if(prefix_queries.empty())continue;std::fill(heads.begin(),heads.end(),-1);for(intid:prefix_queries){constintright=_queries[id].second_right;next[id]=heads[right];heads[right]=id;}std::fill(fenwick.begin(),fenwick.end(),0);intinserted=0;for(intright=1;right<=second_length;right++){constintendpoint=seaweed[right-1];if(endpoint>=0){inserted++;for(intposition=endpoint+1;position<=second_length;position+=position&-position){fenwick[position]++;}}for(intid=heads[right];id!=-1;id=next[id]){constintleft=_queries[id].second_left;intbelow_left=0;for(intposition=left;position>0;position-=position&-position){below_left+=fenwick[position];}constintcrossing=inserted-below_left;answers[id]=(right-left)-crossing;}}}returnanswers;}};template<classFirstSequence,classSecondSequence>PrefixSubstringLcs(FirstSequence&&,SecondSequence&&)->PrefixSubstringLcs<std::decay_t<FirstSequence>,std::decay_t<SecondSequence>>;}// namespace string}// namespace m1une#line 1 "string/rolling_hash.hpp"
#line 8 "string/rolling_hash.hpp"
namespacem1une{namespacestring{// Standard Rolling Hash for static strings.// Precomputes hashes to answer substring queries in O(1).// Provides advanced operations like LCP, lexicographical comparison, and string repetition in O(log N).template<longlongBase=10007,longlongMod=(1LL<<61)-1>structRollingHash{std::strings;std::vector<longlong>hash;std::vector<longlong>power;RollingHash()=default;// Constructs the rolling hash table for the given string.explicitRollingHash(conststd::string&str):s(str){intn=s.size();hash.assign(n+1,0);power.assign(n+1,1);for(inti=0;i<n;++i){// Use __int128_t to prevent overflow during multiplicationhash[i+1]=(static_cast<__int128_t>(hash[i])*Base+s[i])%Mod;power[i+1]=(static_cast<__int128_t>(power[i])*Base)%Mod;}}// Returns the hash of the substring S[l..r) in O(1).longlongget(intl,intr)const{longlongres=hash[r]-(static_cast<__int128_t>(hash[l])*power[r-l])%Mod;if(res<0)res+=Mod;returnres;}// Returns the hash of the concatenated substrings S[l1..r1) and S[l2..r2).longlongconcat(intl1,intr1,intl2,intr2)const{longlongh1=get(l1,r1);longlongh2=get(l2,r2);returncombine(h1,h2,power[r2-l2]);}// Calculates the Longest Common Prefix (LCP) length of S[l1..r1) and S[l2..r2) in O(log N).intlcp(intl1,intr1,intl2,intr2)const{intlen=std::min(r1-l1,r2-l2);intlow=0,high=len+1;while(high-low>1){intmid=low+(high-low)/2;if(get(l1,l1+mid)==get(l2,l2+mid)){low=mid;}else{high=mid;}}returnlow;}// Lexicographically compares S[l1..r1) and S[l2..r2) in O(log N).// Returns -1 if S[l1..r1) < S[l2..r2), 0 if equal, and 1 if S[l1..r1) > S[l2..r2).intcompare(intl1,intr1,intl2,intr2)const{intl=lcp(l1,r1,l2,r2);boolend1=(l1+l==r1);boolend2=(l2+l==r2);if(end1&&end2)return0;if(end1)return-1;if(end2)return1;returns[l1+l]<s[l2+l]?-1:1;}// Returns the hash of the substring S[l..r) repeated 'k' times.longlongrepeat(intl,intr,longlongk)const{longlongh=get(l,r);longlongp=power[r-l];returnrepeat_hash(h,p,k);}// --- Static Helpers for dynamic processing and Monoid integration ---// Computes the hash of a single string in O(N) time and O(1) space.staticlonglongcompute_hash(conststd::string&str){longlongh=0;for(charc:str){h=(static_cast<__int128_t>(h)*Base+c)%Mod;}returnh;}// Combines two hashes. Equivalent to concatenating string 'b' to the right of string 'a'.staticconstexprlonglongcombine(longlongh1,longlongh2,longlongbase_power2){return(static_cast<__int128_t>(h1)*base_power2+h2)%Mod;}// Returns the hash of a string (with hash 'h' and base_power 'p') repeated 'k' times.staticconstexprlonglongrepeat_hash(longlongh,longlongp,longlongk){longlongres_h=0;longlongres_p=1;longlongcur_h=h;longlongcur_p=p;while(k>0){if(k&1){res_h=combine(res_h,cur_h,cur_p);res_p=(static_cast<__int128_t>(res_p)*cur_p)%Mod;}cur_h=combine(cur_h,cur_h,cur_p);cur_p=(static_cast<__int128_t>(cur_p)*cur_p)%Mod;k>>=1;}returnres_h;}// Creates the state pair {hash_value, base_power} for a single character.staticconstexprstd::pair<longlong,longlong>make_single(longlongc){return{c%Mod,Base%Mod};}};}// namespace string}// namespace m1une#line 1 "string/runs.hpp"
#line 5 "string/runs.hpp"
#include<set>
#line 8 "string/runs.hpp"
namespacem1une{namespacestring{structRun{intperiod;intleft;intright;booloperator==(constRun&)const=default;};namespaceinternal{template<classSequence>classRunEnumerator{private:constSequence&_sequence;int_size;std::vector<std::vector<std::pair<int,int>>>_candidates;template<classAccess>staticstd::vector<int>z_algorithm(intlength,Accessaccess){std::vector<int>z(length+1,0);if(length==0)returnz;z[0]=length;intleft=0;intright=0;for(inti=1;i<length;i++){if(i<right)z[i]=std::min(right-i,z[i-left]);while(i+z[i]<length&&access(z[i])==access(i+z[i])){z[i]++;}if(right<i+z[i]){left=i;right=i+z[i];}}returnz;}decltype(auto)element(intindex,boolreversed)const{intoriginal_index=reversed?_size-1-index:index;return_sequence[original_index];}voidadd_candidate(intperiod,intleft,intright,boolreversed){if(reversed){left=_size-left;right=_size-right;std::swap(left,right);}_candidates[period].emplace_back(left,right);}voidcollect(intrange_left,intrange_right,intphase,boolreversed){if(range_right-range_left<=1)return;intmiddle=(range_left+range_right+phase)/2;collect(range_left,middle,phase,reversed);collect(middle,range_right,phase,reversed);intleft_length=middle-range_left;intright_length=range_right-middle;std::vector<int>left_z=z_algorithm(left_length,[&](intindex)->decltype(auto){returnelement(middle-1-index,reversed);});intcombined_length=right_length+range_right-range_left;std::vector<int>right_z=z_algorithm(combined_length,[&](intindex)->decltype(auto){if(index<right_length)returnelement(middle+index,reversed);returnelement(range_left+index-right_length,reversed);});for(intstart=middle-1;start>=range_left;start--){intperiod=middle-start;intextend_left=std::min(start-range_left,left_z[period]);intextend_right=std::min(range_right-middle,right_z[range_right-range_left-period]);intleft=start-extend_left;intright=middle+extend_right;if(right-left>=2*period){add_candidate(period,left,right,reversed);}}}public:explicitRunEnumerator(constSequence&sequence):_sequence(sequence),_size(int(sequence.size())),_candidates(_size/2+1){}std::vector<Run>enumerate(){collect(0,_size,0,true);collect(0,_size,1,false);std::set<std::pair<int,int>>used_intervals;std::vector<Run>result;for(intperiod=1;period<=_size/2;period++){std::vector<std::pair<int,int>>&candidates=_candidates[period];std::sort(candidates.begin(),candidates.end(),[](constauto&first,constauto&second){if(first.first!=second.first){returnfirst.first<second.first;}returnfirst.second>second.second;});intfarthest_right=-1;for(constauto&interval:candidates){if(interval.second<=farthest_right)continue;farthest_right=interval.second;if(!used_intervals.insert(interval).second)continue;result.push_back(Run{period,interval.first,interval.second});}}returnresult;}};}// namespace internal// Returns all runs as (minimum period, maximal half-open interval),// sorted lexicographically by (period, left, right).template<classSequence>std::vector<Run>enumerate_runs(constSequence&sequence){returninternal::RunEnumerator<Sequence>(sequence).enumerate();}}// namespace string}// namespace m1une#line 1 "string/string_hash.hpp"
#line 5 "string/string_hash.hpp"
#include<cstdint>
#line 7 "string/string_hash.hpp"
#include<string_view>namespacem1une{namespacestring{structStringHash{std::uint32_tfirst;std::uint32_tsecond;std::uint32_tfirst_power;std::uint32_tsecond_power;std::size_tlength;friendconstexprbooloperator==(constStringHash&left,constStringHash&right){returnleft.length==right.length&&left.first==right.first&&left.second==right.second;}};namespacestring_hash_detail{inlineconstexprstd::uint64_tfirst_mod=1'000'000'007;inlineconstexprstd::uint64_tsecond_mod=1'000'000'009;inlineconstexprstd::uint64_tbase=911'382'323;}// namespace string_hash_detail// Computes a double polynomial hash. Bytes are interpreted as unsigned.constexprStringHashhash_string(std::string_viewvalue){usingnamespacestring_hash_detail;std::uint64_tfirst=0;std::uint64_tsecond=0;std::uint64_tfirst_power=1;std::uint64_tsecond_power=1;for(charcharacter:value){std::uint64_tsymbol=static_cast<unsignedchar>(character)+std::uint64_t(1);first=(first*base+symbol)%first_mod;second=(second*base+symbol)%second_mod;first_power=first_power*base%first_mod;second_power=second_power*base%second_mod;}returnStringHash{static_cast<std::uint32_t>(first),static_cast<std::uint32_t>(second),static_cast<std::uint32_t>(first_power),static_cast<std::uint32_t>(second_power),value.size(),};}constexprStringHashhash_string(conststd::string&value){returnhash_string(std::string_view(value));}constexprStringHashhash_string(constchar*value){returnhash_string(std::string_view(value));}// Returns the hash of the concatenation represented by `left` and `right`.constexprStringHashconcat_string_hash(constStringHash&left,constStringHash&right){usingnamespacestring_hash_detail;returnStringHash{static_cast<std::uint32_t>((std::uint64_t(left.first)*right.first_power+right.first)%first_mod),static_cast<std::uint32_t>((std::uint64_t(left.second)*right.second_power+right.second)%second_mod),static_cast<std::uint32_t>(std::uint64_t(left.first_power)*right.first_power%first_mod),static_cast<std::uint32_t>(std::uint64_t(left.second_power)*right.second_power%second_mod),left.length+right.length,};}// Hash adapter for std::unordered_map and std::unordered_set.structStringHasher{usingis_transparent=void;constexprstd::size_toperator()(std::string_viewvalue)const{returnoperator()(hash_string(value));}constexprstd::size_toperator()(conststd::string&value)const{returnoperator()(std::string_view(value));}constexprstd::size_toperator()(constchar*value)const{returnoperator()(std::string_view(value));}constexprstd::size_toperator()(constStringHash&value)const{std::uint64_tcombined=(std::uint64_t(value.first)<<32)|value.second;combined^=std::uint64_t(value.length)+0x9e3779b97f4a7c15ULL;combined^=combined>>30;combined*=0xbf58476d1ce4e5b9ULL;combined^=combined>>27;combined*=0x94d049bb133111ebULL;combined^=combined>>31;returnstatic_cast<std::size_t>(combined);}};}// namespace string}// namespace m1une#line 1 "string/suffix_automaton.hpp"
#line 11 "string/suffix_automaton.hpp"
namespacem1une{namespacestring{template<intAlphabetSize=26,intFirstCharacter='a'>structSuffixAutomaton{static_assert(0<AlphabetSize);usingstate_id=int;staticconstexprstate_idroot_state=0;staticconstexprstate_idnull_state=-1;structState{std::array<state_id,AlphabetSize>next;state_idsuffix_link;intlength;intfirst_end;intdirect_occurrences;boolclone;State(intlength_value=0):suffix_link(null_state),length(length_value),first_end(0),direct_occurrences(0),clone(false){next.fill(null_state);}};private:std::vector<State>_states;state_id_last;int_text_length;template<classSymbol>staticintsymbol_index(constSymbol&symbol){intindex=int(symbol)-FirstCharacter;assert(0<=index&&index<AlphabetSize);returnindex;}state_idnew_state(intlength){assert(_states.size()<std::size_t(std::numeric_limits<int>::max()));_states.emplace_back(length);returnint(_states.size())-1;}public:SuffixAutomaton(){clear();}template<classSequence>explicitSuffixAutomaton(constSequence&sequence){clear();build(sequence);}intstate_count()const{returnint(_states.size());}intsize()const{returnstate_count();}boolempty()const{return_text_length==0;}inttext_length()const{return_text_length;}state_idroot()const{returnroot_state;}state_idlast()const{return_last;}constState&state(state_idid)const{assert(0<=id&&id<state_count());return_states[id];}conststd::vector<State>&states()const{return_states;}intminimum_length(state_idid)const{assert(0<=id&&id<state_count());returnid==root_state?0:_states[_states[id].suffix_link].length+1;}template<classSymbol>state_idtransition(state_idid,constSymbol&symbol)const{assert(0<=id&&id<state_count());return_states[id].next[symbol_index(symbol)];}voidreserve(std::size_ttext_capacity){_states.reserve(2*text_capacity);}voidclear(){_states.clear();_states.emplace_back();_last=root_state;_text_length=0;}template<classSymbol>state_idadd(constSymbol&value){intsymbol=symbol_index(value);assert(_text_length<std::numeric_limits<int>::max());_text_length++;state_idcurrent=new_state(_states[_last].length+1);_states[current].first_end=_text_length;_states[current].direct_occurrences=1;state_idp=_last;while(p!=null_state&&_states[p].next[symbol]==null_state){_states[p].next[symbol]=current;p=_states[p].suffix_link;}if(p==null_state){_states[current].suffix_link=root_state;}else{state_idq=_states[p].next[symbol];if(_states[p].length+1==_states[q].length){_states[current].suffix_link=q;}else{state_idclone=new_state(_states[p].length+1);_states[clone]=_states[q];_states[clone].length=_states[p].length+1;_states[clone].direct_occurrences=0;_states[clone].clone=true;while(p!=null_state&&_states[p].next[symbol]==q){_states[p].next[symbol]=clone;p=_states[p].suffix_link;}_states[q].suffix_link=clone;_states[current].suffix_link=clone;}}_last=current;returncurrent;}template<classSequence>voidbuild(constSequence&sequence){for(constauto&symbol:sequence)add(symbol);}template<classSequence>state_idfind(constSequence&sequence)const{state_idcurrent=root_state;for(constauto&symbol:sequence){current=transition(current,symbol);if(current==null_state)returnnull_state;}returncurrent;}template<classSequence>boolcontains(constSequence&sequence)const{returnfind(sequence)!=null_state;}std::vector<state_id>length_order()const{std::vector<int>count(_text_length+1,0);for(constState¤t:_states)count[current.length]++;for(intlength=1;length<=_text_length;length++)count[length]+=count[length-1];std::vector<state_id>order(state_count());for(state_idid=state_count()-1;id>=0;id--){order[--count[_states[id].length]]=id;}returnorder;}std::vector<longlong>occurrence_counts()const{std::vector<longlong>result(state_count(),0);for(state_idid=0;id<state_count();id++){result[id]=_states[id].direct_occurrences;}std::vector<state_id>order=length_order();for(inti=int(order.size())-1;i>0;i--){state_idid=order[i];result[_states[id].suffix_link]+=result[id];}returnresult;}std::vector<bool>terminal_states()const{std::vector<bool>result(state_count(),false);for(state_idid=_last;id!=null_state;id=_states[id].suffix_link){result[id]=true;}returnresult;}longlongdistinct_substring_count()const{longlongresult=0;for(state_idid=1;id<state_count();id++){result+=_states[id].length-_states[_states[id].suffix_link].length;}returnresult;}std::pair<int,int>longest_representative(state_idid)const{assert(0<=id&&id<state_count());intend=_states[id].first_end;return{end-_states[id].length,end};}template<classSequence>std::pair<int,int>representative_occurrence(constSequence&sequence)const{state_idid=root_state;intlength=0;for(constauto&symbol:sequence){id=transition(id,symbol);if(id==null_state)return{-1,-1};length++;}intend=_states[id].first_end;return{end-length,end};}template<classSequence>std::pair<int,int>longest_common_substring(constSequence&sequence)const{state_idcurrent=root_state;intcurrent_length=0;intbest_length=0;intbest_end=0;intend=0;for(constauto&value:sequence){intsymbol=symbol_index(value);while(current!=root_state&&_states[current].next[symbol]==null_state){current=_states[current].suffix_link;current_length=std::min(current_length,_states[current].length);}state_idnext=_states[current].next[symbol];if(next==null_state){current=root_state;current_length=0;}else{current=next;current_length++;}end++;if(best_length<current_length){best_length=current_length;best_end=end;}}return{best_end-best_length,best_end};}};}// namespace string}// namespace m1une#line 1 "string/suffix_tree.hpp"
#line 11 "string/suffix_tree.hpp"
namespacem1une{namespacestring{template<intAlphabetSize=26,intFirstCharacter='a'>structSuffixTree{static_assert(0<AlphabetSize);usingnode_id=int;staticconstexprnode_idroot_node=0;staticconstexprnode_idnull_node=-1;staticconstexprintterminal_symbol=AlphabetSize;structNode{std::array<node_id,AlphabetSize+1>next;node_idsuffix_link;node_idparent;intleft;intright;intsuffix_start;intrepresentative_suffix;intleaf_count;intincoming_symbol;node_idfirst_child;node_idnext_sibling;intchild_count;Node(intleft_value=0,intright_value=0,node_idparent_value=null_node):suffix_link(null_node),parent(parent_value),left(left_value),right(right_value),suffix_start(-1),representative_suffix(-1),leaf_count(0),incoming_symbol(-1),first_child(null_node),next_sibling(null_node),child_count(0){next.fill(null_node);}};structLocus{node_idnode;intoffset;explicitoperatorbool()const{returnnode!=null_node;}friendbooloperator==(constLocus&,constLocus&)=default;};private:structActivePoint{node_idnode;intoffset;};std::vector<Node>_nodes;std::vector<int>_text;ActivePoint_active;int_text_length;template<classSymbol>staticintsymbol_index(constSymbol&symbol){intindex=int(symbol)-FirstCharacter;assert(0<=index&&index<AlphabetSize);returnindex;}intedge_length_unchecked(node_idid)const{return_nodes[id].right-_nodes[id].left;}node_idnew_node(intleft,intright,node_idparent){assert(_nodes.size()<std::size_t(std::numeric_limits<int>::max()));_nodes.emplace_back(left,right,parent);returnint(_nodes.size())-1;}ActivePointgo(ActivePointpoint,intleft,intright)const{while(left<right){if(point.offset==edge_length_unchecked(point.node)){point={_nodes[point.node].next[_text[left]],0};if(point.node==null_node)returnpoint;}else{if(_text[_nodes[point.node].left+point.offset]!=_text[left]){return{null_node,0};}intremaining=edge_length_unchecked(point.node)-point.offset;if(right-left<remaining){point.offset+=right-left;returnpoint;}left+=remaining;point.offset=edge_length_unchecked(point.node);}}returnpoint;}node_idsplit(ActivePointpoint){if(point.offset==edge_length_unchecked(point.node))returnpoint.node;if(point.offset==0)return_nodes[point.node].parent;node_idchild=point.node;node_idparent=_nodes[child].parent;intleft=_nodes[child].left;node_idmiddle=new_node(left,left+point.offset,parent);_nodes[parent].next[_text[left]]=middle;_nodes[middle].next[_text[left+point.offset]]=child;_nodes[child].parent=middle;_nodes[child].left+=point.offset;returnmiddle;}node_idget_suffix_link(node_idid){if(_nodes[id].suffix_link!=null_node)return_nodes[id].suffix_link;node_idparent=_nodes[id].parent;if(parent==null_node)returnroot_node;node_idparent_link=get_suffix_link(parent);ActivePointpoint={parent_link,edge_length_unchecked(parent_link)};intleft=_nodes[id].left+(parent==root_node);point=go(point,left,_nodes[id].right);assert(point.node!=null_node);return_nodes[id].suffix_link=split(point);}voidextend(intposition){while(true){ActivePointnext=go(_active,position,position+1);if(next.node!=null_node){_active=next;return;}node_idmiddle=split(_active);node_idleaf=new_node(position,int(_text.size()),middle);_nodes[middle].next[_text[position]]=leaf;_active.node=get_suffix_link(middle);_active.offset=edge_length_unchecked(_active.node);if(middle==root_node)return;}}voidfinish_metadata(){std::vector<node_id>order;order.reserve(_nodes.size());order.push_back(root_node);std::vector<int>depth(_nodes.size(),0);for(std::size_ti=0;i<order.size();i++){node_idid=order[i];node_idprevious_child=null_node;for(intsymbol=0;symbol<=terminal_symbol;symbol++){node_idchild=_nodes[id].next[symbol];if(child==null_node)continue;_nodes[child].incoming_symbol=symbol;if(previous_child==null_node){_nodes[id].first_child=child;}else{_nodes[previous_child].next_sibling=child;}previous_child=child;_nodes[id].child_count++;depth[child]=depth[id]+edge_length_unchecked(child);order.push_back(child);}}for(inti=int(order.size())-1;i>=0;i--){node_idid=order[i];boolleaf=true;for(node_idchild:_nodes[id].next){if(child==null_node)continue;leaf=false;_nodes[id].leaf_count+=_nodes[child].leaf_count;if(_nodes[id].representative_suffix==-1){_nodes[id].representative_suffix=_nodes[child].representative_suffix;}}if(leaf){_nodes[id].suffix_start=int(_text.size())-depth[id];_nodes[id].representative_suffix=_nodes[id].suffix_start;_nodes[id].leaf_count=1;}}}voidinitialize(){_nodes.clear();_nodes.reserve(2*_text.size()+1);_nodes.emplace_back();_nodes[root_node].suffix_link=root_node;_active={root_node,0};for(intposition=0;position<int(_text.size());position++)extend(position);finish_metadata();}public:SuffixTree(){clear();}template<classSequence>explicitSuffixTree(constSequence&sequence){build(sequence);}intsize()const{returnnode_count();}boolempty()const{return_text_length==0;}intnode_count()const{returnint(_nodes.size());}inttext_length()const{return_text_length;}node_idroot()const{returnroot_node;}constNode&node(node_idid)const{assert(0<=id&&id<node_count());return_nodes[id];}conststd::vector<Node>&nodes()const{return_nodes;}intedge_length(node_idid)const{assert(0<=id&&id<node_count());returnedge_length_unchecked(id);}boolis_leaf(node_idid)const{assert(0<=id&&id<node_count());return_nodes[id].suffix_start!=-1;}template<classSymbol>node_idchild(node_idid,constSymbol&symbol)const{assert(0<=id&&id<node_count());return_nodes[id].next[symbol_index(symbol)];}node_idchild_by_index(node_idid,intsymbol)const{assert(0<=id&&id<node_count());assert(0<=symbol&&symbol<=terminal_symbol);return_nodes[id].next[symbol];}template<classCallback>voidfor_each_child(node_idid,Callbackcallback)const{assert(0<=id&&id<node_count());for(node_idchild_id=_nodes[id].first_child;child_id!=null_node;child_id=_nodes[child_id].next_sibling){callback(_nodes[child_id].incoming_symbol,child_id);}}voidclear(){_text.clear();_text.push_back(terminal_symbol);_text_length=0;initialize();}template<classSequence>voidbuild(constSequence&sequence){_text.clear();for(constauto&symbol:sequence)_text.push_back(symbol_index(symbol));assert(_text.size()<std::size_t(std::numeric_limits<int>::max()));_text_length=int(_text.size());_text.push_back(terminal_symbol);initialize();}template<classSequence>Locusfind(constSequence&sequence)const{ActivePointpoint={root_node,0};for(constauto&value:sequence){intsymbol=symbol_index(value);if(point.offset==edge_length_unchecked(point.node)){point={_nodes[point.node].next[symbol],0};if(point.node==null_node)return{null_node,0};}if(_text[_nodes[point.node].left+point.offset]!=symbol){return{null_node,0};}point.offset++;}return{point.node,point.offset};}template<classSequence>boolcontains(constSequence&sequence)const{returnbool(find(sequence));}template<classSequence>intcount_occurrences(constSequence&sequence)const{Locuslocus=find(sequence);returnlocus?_nodes[locus.node].leaf_count:0;}template<classSequence>std::pair<int,int>representative_occurrence(constSequence&sequence)const{Locuslocus={root_node,0};intlength=0;for(constauto&value:sequence){intsymbol=symbol_index(value);if(locus.offset==edge_length_unchecked(locus.node)){locus={_nodes[locus.node].next[symbol],0};if(locus.node==null_node)return{-1,-1};}if(_text[_nodes[locus.node].left+locus.offset]!=symbol)return{-1,-1};locus.offset++;length++;}intleft=_nodes[locus.node].representative_suffix;return{left,left+length};}longlongdistinct_substring_count()const{longlongresult=0;for(node_idid=1;id<node_count();id++){result+=std::max(0,std::min(_nodes[id].right,_text_length)-_nodes[id].left);}returnresult;}};}// namespace string}// namespace m1une#line 1 "string/trie.hpp"
#line 9 "string/trie.hpp"
namespacem1une{namespacestring{// A multiset trie for a contiguous character alphabet.template<intAlphabetSize=26,intFirstCharacter='a'>structTrie{static_assert(0<AlphabetSize);usingnode_id=int;staticconstexprnode_idnull_node=-1;structNode{std::array<node_id,AlphabetSize>child;intsubtree_count;intterminal_count;Node():subtree_count(0),terminal_count(0){child.fill(null_node);}};private:std::vector<Node>_nodes;int_distinct_size;template<classSymbol>staticintsymbol_index(constSymbol&symbol){intindex=int(symbol)-FirstCharacter;assert(0<=index&&index<AlphabetSize);returnindex;}node_idnew_node(){assert(_nodes.size()<std::size_t(std::numeric_limits<int>::max()));_nodes.emplace_back();returnint(_nodes.size())-1;}template<classSequence>node_idfind_node(constSequence&sequence)const{node_idnode=0;for(constauto&symbol:sequence){node=_nodes[node].child[symbol_index(symbol)];if(node==null_node||_nodes[node].subtree_count==0){returnnull_node;}}returnnode;}public:Trie():_nodes(1),_distinct_size(0){}intsize()const{return_nodes[0].subtree_count;}intdistinct_size()const{return_distinct_size;}boolempty()const{returnsize()==0;}node_idroot()const{return0;}constNode&node(node_idid)const{assert(0<=id&&std::size_t(id)<_nodes.size());return_nodes[id];}template<classSequence>node_idfind(constSequence&sequence)const{returnfind_node(sequence);}std::size_tnode_count()const{return_nodes.size();}voidreserve(std::size_tnode_capacity){_nodes.reserve(node_capacity);}voidclear(){_nodes.clear();_nodes.emplace_back();_distinct_size=0;}template<classSequence>node_idinsert(constSequence&sequence,intmultiplicity=1){assert(0<multiplicity);node_idnode=0;_nodes[node].subtree_count+=multiplicity;for(constauto&symbol:sequence){intindex=symbol_index(symbol);node_idchild=_nodes[node].child[index];if(child==null_node){child=new_node();_nodes[node].child[index]=child;}node=child;_nodes[node].subtree_count+=multiplicity;}if(_nodes[node].terminal_count==0)_distinct_size++;_nodes[node].terminal_count+=multiplicity;returnnode;}template<classSequence>intcount(constSequence&sequence)const{node_idnode=find_node(sequence);returnnode==null_node?0:_nodes[node].terminal_count;}template<classSequence>boolcontains(constSequence&sequence)const{returncount(sequence)!=0;}// Returns the number of stored strings beginning with prefix.template<classSequence>intprefix_count(constSequence&prefix)const{node_idnode=find_node(prefix);returnnode==null_node?0:_nodes[node].subtree_count;}template<classSequence>boolstarts_with(constSequence&prefix)const{returnprefix_count(prefix)!=0;}template<classSequence>boolerase_one(constSequence&sequence){node_idterminal=find_node(sequence);if(terminal==null_node||_nodes[terminal].terminal_count==0){returnfalse;}intnode=0;_nodes[node].subtree_count--;for(constauto&symbol:sequence){node=_nodes[node].child[symbol_index(symbol)];_nodes[node].subtree_count--;}_nodes[node].terminal_count--;if(_nodes[node].terminal_count==0)_distinct_size--;returntrue;}template<classSequence>boolerase(constSequence&sequence){returnerase_one(sequence);}template<classSequence>interase_all(constSequence&sequence){intmultiplicity=count(sequence);if(multiplicity==0)return0;intnode=0;_nodes[node].subtree_count-=multiplicity;for(constauto&symbol:sequence){node=_nodes[node].child[symbol_index(symbol)];_nodes[node].subtree_count-=multiplicity;}_nodes[node].terminal_count=0;_distinct_size--;returnmultiplicity;}// Calls callback(length, multiplicity) for every stored prefix.// The empty prefix is reported with length 0 when it is stored.template<classSequence,classCallback>voidfor_each_prefix(constSequence&sequence,Callbackcallback)const{intnode=0;if(_nodes[node].terminal_count!=0){callback(0,_nodes[node].terminal_count);}intlength=0;for(constauto&symbol:sequence){node=_nodes[node].child[symbol_index(symbol)];if(node==null_node||_nodes[node].subtree_count==0)return;length++;if(_nodes[node].terminal_count!=0){callback(length,_nodes[node].terminal_count);}}}// Returns the length of the longest stored string that is a prefix.// Returns -1 when no stored prefix exists.template<classSequence>intlongest_prefix(constSequence&sequence)const{intresult=_nodes[0].terminal_count==0?-1:0;for_each_prefix(sequence,[&result](intlength,int){result=length;});returnresult;}};}// namespace string}// namespace m1une#line 1 "string/wildcard_pattern_matching.hpp"
#line 7 "string/wildcard_pattern_matching.hpp"
#line 1 "math/fps/convolution.hpp"
#line 8 "math/fps/convolution.hpp"
#include<cstring>
#include<new>
#line 13 "math/fps/convolution.hpp"
#if defined(__GNUC__) && !defined(__clang__) && \
(defined(__x86_64__) || defined(__i386__)) && \
!defined(M1UNE_FPS_DISABLE_X86_SIMD)
#include<immintrin.h>
#define M1UNE_FPS_HAS_X86_SIMD 1
#pragma GCC push_options
#pragma GCC target("avx2,bmi")
#endif
#line 1 "math/fps/internal/ntt998_faster.hpp"
#ifdef M1UNE_FPS_HAS_X86_SIMD
#line 9 "math/fps/internal/ntt998_faster.hpp"
#include<immintrin.h>namespacem1une{namespacefps{namespaceinternal{namespacefast998_v2{// Fixed-modulus AVX2 transform with an in-register degree-8 residue product.usingu32=unsigned;usingu64=unsignedlonglong;usingidt=std::size_t;usingI256=__m256i;inlinevoidstore256(void*p,I256x){_mm256_store_si256((I256*)p,x);}inlineI256load256(constvoid*p){return_mm256_load_si256((constI256*)p);}constexpru32shrk(u32x,u32M){returnstd::min(x,x-M);}constexpru32dilt(u32x,u32M){returnstd::min(x,x+M);}constexpru32reduce(u64x,u32niv,u32M){return(x+u64(u32(x)*niv)*M)>>32;}constexpru32mul(u32x,u32y,u32niv,u32M){returnreduce(u64(x)*y,niv,M);}constexpru32mul_s(u32x,u32y,u32niv,u32M){returnshrk(reduce(u64(x)*y,niv,M),M);}constexpru32qpw(u32a,u32b,u32niv,u32M,u32r){for(;b;b>>=1,a=mul(a,a,niv,M)){if(b&1){r=mul(r,a,niv,M);}}returnr;}constexpru32qpw_s(u32a,u32b,u32niv,u32M,u32r){returnshrk(qpw(a,b,niv,M,r),M);}inlineI256shrk32(I256x,I256M){return_mm256_min_epu32(x,_mm256_sub_epi32(x,M));}inlineI256dilt32(I256x,I256M){return_mm256_min_epu32(x,_mm256_add_epi32(x,M));}inlineI256Ladd32(I256x,I256y,I256){return_mm256_add_epi32(x,y);}inlineI256Lsub32(I256x,I256y,I256M){return_mm256_add_epi32(_mm256_sub_epi32(x,y),M);}inlineI256add32(I256x,I256y,I256M){returnshrk32(_mm256_add_epi32(x,y),M);}inlineI256sub32(I256x,I256y,I256M){returndilt32(_mm256_sub_epi32(x,y),M);}template<intmsk>inlineI256neg32_m(I256x,I256M){return_mm256_blend_epi32(x,_mm256_sub_epi32(M,x),msk);}inlineI256reduce(I256a,I256b,I256niv,I256M){I256c=_mm256_mul_epu32(a,niv),d=_mm256_mul_epu32(b,niv);c=_mm256_mul_epu32(c,M),d=_mm256_mul_epu32(d,M);return_mm256_blend_epi32(_mm256_srli_epi64(_mm256_add_epi64(a,c),32),_mm256_add_epi64(b,d),0xaa);}inlineI256mul(I256a,I256b,I256niv,I256M){returnreduce(_mm256_mul_epu32(a,b),_mm256_mul_epu32(_mm256_srli_epi64(a,32),_mm256_srli_epi64(b,32)),niv,M);}inlineI256mul_s(I256a,I256b,I256niv,I256M){returnshrk32(mul(a,b,niv,M),M);}inlineI256mul_bsm(I256a,I256b,I256niv,I256M){returnreduce(_mm256_mul_epu32(a,b),_mm256_mul_epu32(_mm256_srli_epi64(a,32),b),niv,M);}inlineI256mul_bsmfxd(I256a,I256b,I256bniv,I256M){I256cc=_mm256_mul_epu32(a,bniv),dd=_mm256_mul_epu32(_mm256_srli_epi64(a,32),bniv);I256c=_mm256_mul_epu32(a,b),d=_mm256_mul_epu32(_mm256_srli_epi64(a,32),b);cc=_mm256_mul_epu32(cc,M),dd=_mm256_mul_epu32(dd,M);return_mm256_blend_epi32(_mm256_srli_epi64(_mm256_add_epi64(c,cc),32),_mm256_add_epi64(d,dd),0xaa);}inlineI256mul_bfxd(I256a,I256b,I256bniv,I256M){I256cc=_mm256_mul_epu32(a,bniv),dd=_mm256_mul_epu32(_mm256_srli_epi64(a,32),_mm256_srli_epi64(bniv,32));I256c=_mm256_mul_epu32(a,b),d=_mm256_mul_epu32(_mm256_srli_epi64(a,32),_mm256_srli_epi64(b,32));cc=_mm256_mul_epu32(cc,M),dd=_mm256_mul_epu32(dd,M);return_mm256_blend_epi32(_mm256_srli_epi64(_mm256_add_epi64(c,cc),32),_mm256_add_epi64(d,dd),0xaa);}inlineI256mul_upd_rt(I256a,I256bu,I256M){I256cc=_mm256_mul_epu32(a,bu),c=_mm256_mul_epu32(a,_mm256_srli_epi64(bu,32));cc=_mm256_mul_epu32(cc,M);returnshrk32(_mm256_srli_epi64(_mm256_add_epi64(c,cc),32),M);}constexprauto_mxlg=26,_lg_itth=6;constexprauto_itth=idt(1)<<_lg_itth;static_assert(_lg_itth%2==0);structFNTT32_info{u32mod,mod2,niv,one,r2,r3,img,imgniv,RT1[_mxlg];alignas(32)std::array<u32,8>rt3[_mxlg-2],rt3i[_mxlg-2],bwbr,bwb,bwbi,rt4[_mxlg-3],rt4niv[_mxlg-3],rt4i[_mxlg-3],rt4iniv[_mxlg-3],pr2,pr4,pr2niv,pr4niv,pr2i,pr2iniv,pr4i,pr4iniv;constexprFNTT32_info(constu32m):mod(m),mod2(m*2),niv([&]{u32n=2+m;for(inti=0;i<4;++i){n*=2+m*n;}returnn;}()),one((-m)%m),r2((-u64(m))%m),r3(mul_s(r2,r2,niv,m)),img{},imgniv{},RT1{},rt3{},rt3i{},bwbr{},bwb{},bwbi{},rt4{},rt4niv{},rt4i{},rt4iniv{},pr2{},pr4{},pr2niv{},pr4niv{},pr2i{},pr2iniv{},pr4i{},pr4iniv{}{constintk=__builtin_ctz(m-1);u32_g=mul(3,r2,niv,mod);for(;;++_g){if(qpw_s(_g,mod>>1,niv,mod,one)!=one){break;}}_g=qpw(_g,mod>>k,niv,mod,one);u32rt1[_mxlg-1],rt1i[_mxlg-1];rt1[k-2]=_g,rt1i[k-2]=qpw(_g,mod-2,niv,mod,one);for(inti=k-2;i>0;--i){rt1[i-1]=mul(rt1[i],rt1[i],niv,mod);rt1i[i-1]=mul(rt1i[i],rt1i[i],niv,mod);}RT1[k-1]=qpw_s(_g,3,niv,mod,one);for(inti=k-1;i>0;--i){RT1[i-1]=mul_s(RT1[i],RT1[i],niv,mod);}img=rt1[0],imgniv=img*niv;bwbr={one,0,one,0,one};bwb={rt1[1],0,rt1[0],0,mod-mul_s(rt1[0],rt1[1],niv,mod)};bwbi={rt1i[1],0,rt1i[0],0,mul_s(rt1i[0],rt1i[1],niv,mod)};u32pr=one,pri=one;for(inti=0;i<k-2;++i){constu32r=mul_s(pr,rt1[i+1],niv,mod),ri=mul_s(pri,rt1i[i+1],niv,mod);constu32r2=mul_s(r,r,niv,mod),r2i=mul_s(ri,ri,niv,mod);constu32r3=mul_s(r,r2,niv,mod),r3i=mul_s(ri,r2i,niv,mod);rt3[i]={r*niv,r,r2*niv,r2,r3*niv,r3};rt3i[i]={ri*niv,ri,r2i*niv,r2i,r3i*niv,r3i};pr=mul(pr,rt1i[i+1],niv,mod),pri=mul(pri,rt1[i+1],niv,mod);}pr=one,pri=one;for(inti=0;i<k-3;++i){constu32r=mul_s(pr,rt1[i+2],niv,mod),ri=mul_s(pri,rt1i[i+2],niv,mod);rt4[i][0]=rt4i[i][0]=one;for(intj=1;j<8;++j){rt4[i][j]=mul_s(rt4[i][j-1],r,niv,mod);rt4i[i][j]=mul_s(rt4i[i][j-1],ri,niv,mod);}for(intj=0;j<8;++j){rt4niv[i][j]=rt4[i][j]*niv;rt4iniv[i][j]=rt4i[i][j]*niv;}pr=mul(pr,rt1i[i+2],niv,mod),pri=mul(pri,rt1[i+2],niv,mod);}pr2={one,one,one,img,one,one,one,img};pr4={one,one,one,one,one,rt1[1],img,mul_s(img,rt1[1],niv,mod)};constu32nr2=mod-r2,imgr2=mul_s(img,r2,niv,mod);pr2i={nr2,nr2,nr2,imgr2,nr2,nr2,nr2,imgr2};pr4i={one,one,one,one,one,rt1i[1],rt1i[0],mul_s(rt1i[0],rt1i[1],niv,mod)};for(intj=0;j<8;++j){pr2niv[j]=pr2[j]*niv,pr4niv[j]=pr4[j]*niv;pr2iniv[j]=pr2i[j]*niv,pr4iniv[j]=pr4i[j]*niv;}}};inlinevoidvector_dif(I256*constf,constidtn,constFNTT32_info*info){alignas(32)std::array<u32,8>st_1[_mxlg>>1];constI256Mod=_mm256_set1_epi32(info->mod),Mod2=_mm256_set1_epi32(info->mod2),Niv=_mm256_set1_epi32(info->niv);constI256Img=_mm256_set1_epi32(info->img),ImgNiv=_mm256_set1_epi32(info->imgniv),id=_mm256_setr_epi32(0,2,0,4,0,2,0,4);constintlgn=__builtin_ctzll(n);std::fill(st_1,st_1+(lgn>>1),info->bwb);constidtnn=n>>(lgn&1),m=std::min(n,_itth),mm=std::min(nn,_itth);// I256 rr=_mm256_set1_epi32(info->one);if(nn!=n){for(idti=0;i<nn;++i){autoconstp0=f+i,p1=f+nn+i;constautof0=load256(p0),f1=load256(p1);constautog0=add32(f0,f1,Mod2),g1=Lsub32(f0,f1,Mod2);store256(p0,g0),store256(p1,g1);}}for(idtL=nn>>2;L>0;L>>=2){for(idti=0;i<L;++i){autoconstp0=f+i,p1=p0+L,p2=p1+L,p3=p2+L;constautof1=load256(p1),f3=load256(p3),f2=load256(p2),f0=load256(p0);constautog3=mul_bsmfxd(Lsub32(f1,f3,Mod2),Img,ImgNiv,Mod),g1=add32(f1,f3,Mod2);constautog0=add32(f0,f2,Mod2),g2=sub32(f0,f2,Mod2);constautoh0=add32(g0,g1,Mod2),h1=Lsub32(g0,g1,Mod2);constautoh2=Ladd32(g2,g3,Mod2),h3=Lsub32(g2,g3,Mod2);store256(p0,h0),store256(p1,h1),store256(p2,h2),store256(p3,h3);}}for(idtj=0;j<n;j+=m){intt=((j==0)?std::min(_lg_itth,lgn):__builtin_ctzll(j))&-2,p=(t-2)>>1;for(idtL=(idt(1)<<t)>>2;L>=_itth;L>>=2,t-=2,--p){autort=load256(st_1+p);constautor1=_mm256_permutevar8x32_epi32(rt,id);constautor1Niv=_mm256_permutevar8x32_epi32(_mm256_mul_epu32(rt,Niv),id);rt=mul_upd_rt(rt,load256(info->rt3+__builtin_ctzll(~j>>t)),Mod);constautor2=_mm256_shuffle_epi32(r1,_MM_PERM_BBBB),nr3=_mm256_shuffle_epi32(r1,_MM_PERM_DDDD);constautor2Niv=_mm256_shuffle_epi32(r1Niv,_MM_PERM_BBBB),nr3Niv=_mm256_shuffle_epi32(r1Niv,_MM_PERM_DDDD);store256(st_1+p,rt);for(idti=0;i<L;++i){autoconstp0=f+i+j,p1=p0+L,p2=p1+L,p3=p2+L;constautof1=load256(p1),f3=load256(p3),f2=load256(p2),f0=load256(p0);constautog1=mul_bsmfxd(f1,r1,r1Niv,Mod),ng3=mul_bsmfxd(f3,nr3,nr3Niv,Mod);constautog2=mul_bsmfxd(f2,r2,r2Niv,Mod),g0=shrk32(f0,Mod2);constautoh3=mul_bsmfxd(Ladd32(g1,ng3,Mod2),Img,ImgNiv,Mod),h1=sub32(g1,ng3,Mod2);constautoh0=add32(g0,g2,Mod2),h2=sub32(g0,g2,Mod2);constautou0=Ladd32(h0,h1,Mod2),u1=Lsub32(h0,h1,Mod2);constautou2=Ladd32(h2,h3,Mod2),u3=Lsub32(h2,h3,Mod2);store256(p0,u0),store256(p1,u1),store256(p2,u2),store256(p3,u3);}}I256*constg=f+j;for(idtl=mm,L=mm>>2;L;l=L,L>>=2,t-=2,--p){autort=load256(st_1+p);for(idti=(j==0?l:0),k=(j+i)>>t;i<m;i+=l,++k){constautor1=_mm256_permutevar8x32_epi32(rt,id);constautor2=_mm256_shuffle_epi32(r1,_MM_PERM_BBBB);constautonr3=_mm256_shuffle_epi32(r1,_MM_PERM_DDDD);for(idtj=0;j<L;++j){autoconstp0=g+i+j,p1=p0+L,p2=p1+L,p3=p2+L;constautof1=load256(p1),f3=load256(p3),f2=load256(p2),f0=load256(p0);constautog1=mul_bsm(f1,r1,Niv,Mod),ng3=mul_bsm(f3,nr3,Niv,Mod);constautog2=mul_bsm(f2,r2,Niv,Mod),g0=shrk32(f0,Mod2);constautoh3=mul_bsmfxd(Ladd32(g1,ng3,Mod2),Img,ImgNiv,Mod),h1=sub32(g1,ng3,Mod2);constautoh0=add32(g0,g2,Mod2),h2=sub32(g0,g2,Mod2);constautou0=Ladd32(h0,h1,Mod2),u1=Lsub32(h0,h1,Mod2);constautou2=Ladd32(h2,h3,Mod2),u3=Lsub32(h2,h3,Mod2);store256(p0,u0),store256(p1,u1),store256(p2,u2),store256(p3,u3);}rt=mul_upd_rt(rt,load256(info->rt3+__builtin_ctzll(~k)),Mod);}store256(st_1+p,rt);}// const auto pr2=load256(&info->pr2),pr4=load256(&info->pr4);// const auto pr2Niv=load256(&info->pr2niv),pr4Niv=load256(&info->pr4niv);// for(idt i=j;i<j+m;++i){// auto fi=load256(f+i);// fi=mul(fi,rr,Niv,Mod);// rr=shrk32(mul_bfxd(rr,load256(info->rt4+__builtin_ctzll(~i)),load256(info->rt4niv+__builtin_ctzll(~i)),Mod),Mod);// fi=mul_bfxd(Ladd32(neg32_m<0xf0>(fi,Mod2),_mm256_permute2x128_si256(fi,fi,1),Mod2),pr4,pr4Niv,Mod);// fi=mul_bfxd(Ladd32(neg32_m<0xcc>(fi,Mod2),_mm256_shuffle_epi32(fi,0x4e),Mod2),pr2,pr2Niv,Mod);// fi=sub32(_mm256_shuffle_epi32(fi,0xb1),neg32_m<0x55>(fi,Mod2),Mod2);// store256(f+i,fi);// }}}template<boolshrk=false>inlinevoidvector_dit(I256*constf,idtn,constFNTT32_info*constinfo){alignas(32)std::array<u32,8>st_1[_mxlg>>1];constI256Mod=_mm256_set1_epi32(info->mod),Mod2=_mm256_set1_epi32(info->mod2),Niv=_mm256_set1_epi32(info->niv);constI256Img=_mm256_set1_epi32(info->img),ImgNiv=_mm256_set1_epi32(info->imgniv),id=_mm256_setr_epi32(0,2,0,4,0,2,0,4);constintlgn=__builtin_ctzll(n);std::fill(st_1,st_1+(_lg_itth>>1),info->bwbr);std::fill(st_1+(_lg_itth>>1),st_1+(_mxlg>>1),info->bwbi);constidtnn=n>>(lgn&1),mm=std::min(nn,_itth);// I256 rr=_mm256_set1_epi32((info->mod-1)>>(lgn+3));for(idtj=0;j<n;j+=mm){// const auto pr2=load256(&info->pr2i),pr4=load256(&info->pr4i);// const auto pr2Niv=load256(&info->pr2iniv),pr4Niv=load256(&info->pr4iniv);// for(idt i=j;i<j+mm;++i){// auto fi=load256(f+i);// const auto rt=rr;// rr=shrk32(mul_bfxd(rr,load256(info->rt4i+__builtin_ctzll(~i)),load256(info->rt4iniv+__builtin_ctzll(~i)),Mod),Mod);// fi=mul_bfxd(Ladd32(neg32_m<0xaa>(fi,Mod2),_mm256_shuffle_epi32(fi,0xb1),Mod2),pr2,pr2Niv,Mod);// fi=mul_bfxd(Ladd32(neg32_m<0xcc>(fi,Mod2),_mm256_shuffle_epi32(fi,0x4e),Mod2),pr4,pr4Niv,Mod);// fi=mul(Ladd32(neg32_m<0xf0>(fi,Mod2),_mm256_permute2x128_si256(fi,fi,1),Mod2),rt,Niv,Mod);// store256(f+i,fi);// }I256*constg=f+j;intt=2,p=0;for(idtl=4,L=1;l<=mm;L=l,l<<=2,t+=2,++p){autort=load256(st_1+p);for(idti=0,k=j>>t;i<mm;i+=l,++k){constautor1=_mm256_permutevar8x32_epi32(rt,id);constautor2=_mm256_shuffle_epi32(r1,_MM_PERM_BBBB);constautor3=_mm256_shuffle_epi32(r1,_MM_PERM_DDDD);for(idtj=0;j<L;++j){autoconstp0=g+i+j,p1=p0+L,p2=p1+L,p3=p2+L;constautof0=load256(p0),f1=load256(p1),f2=load256(p2),f3=load256(p3);constautog0=add32(f0,f1,Mod2),g1=sub32(f0,f1,Mod2);constautog2=add32(f2,f3,Mod2),g3=mul_bsmfxd(Lsub32(f3,f2,Mod2),Img,ImgNiv,Mod);constautoh0=Ladd32(g0,g2,Mod2),h1=Ladd32(g1,g3,Mod2);constautoh2=Lsub32(g0,g2,Mod2),h3=Lsub32(g1,g3,Mod2);constautou0=shrk32(h0,Mod2),u1=mul_bsm(h1,r1,Niv,Mod);constautou2=mul_bsm(h2,r2,Niv,Mod),u3=mul_bsm(h3,r3,Niv,Mod);store256(p0,u0),store256(p1,u1),store256(p2,u2),store256(p3,u3);}rt=mul_upd_rt(rt,load256(info->rt3i+__builtin_ctzll(~k)),Mod);}store256(st_1+p,rt);}inttt=std::min(__builtin_ctzll(~(j>>_lg_itth))+_lg_itth,lgn);for(idtL=_itth,l=L<<2;t<=tt;L=l,l<<=2,t+=2,++p){if((j+_itth)==l){if(shrk&&l==n){for(idti=0;i<L;++i){autoconstp0=f+i,p1=p0+L,p2=p1+L,p3=p2+L;constautof2=load256(p2),f3=load256(p3),f0=load256(p0),f1=load256(p1);constautog3=mul_bsmfxd(Lsub32(f3,f2,Mod2),Img,ImgNiv,Mod),g2=add32(f2,f3,Mod2);constautog0=add32(f0,f1,Mod2),g1=sub32(f0,f1,Mod2);constautoh0=add32(g0,g2,Mod2),h1=add32(g1,g3,Mod2);constautoh2=sub32(g0,g2,Mod2),h3=sub32(g1,g3,Mod2);constautou0=shrk32(h0,Mod),u1=shrk32(h1,Mod);constautou2=shrk32(h2,Mod),u3=shrk32(h3,Mod);store256(p0,u0),store256(p1,u1),store256(p2,u2),store256(p3,u3);}}else{for(idti=0;i<L;++i){autoconstp0=f+i,p1=p0+L,p2=p1+L,p3=p2+L;constautof2=load256(p2),f3=load256(p3),f0=load256(p0),f1=load256(p1);constautog3=mul_bsmfxd(Lsub32(f3,f2,Mod2),Img,ImgNiv,Mod),g2=add32(f2,f3,Mod2);constautog0=add32(f0,f1,Mod2),g1=sub32(f0,f1,Mod2);constautoh0=add32(g0,g2,Mod2),h1=add32(g1,g3,Mod2);constautoh2=sub32(g0,g2,Mod2),h3=sub32(g1,g3,Mod2);store256(p0,h0),store256(p1,h1),store256(p2,h2),store256(p3,h3);}}}else{autort=load256(st_1+p);constautor1=_mm256_permutevar8x32_epi32(rt,id);constautor1Niv=_mm256_permutevar8x32_epi32(_mm256_mul_epu32(rt,Niv),id);rt=mul_upd_rt(rt,load256(info->rt3i+__builtin_ctzll(~j>>t)),Mod);constautor2=_mm256_shuffle_epi32(r1,_MM_PERM_BBBB),r3=_mm256_shuffle_epi32(r1,_MM_PERM_DDDD);constautor2Niv=_mm256_shuffle_epi32(r1Niv,_MM_PERM_BBBB),r3Niv=_mm256_shuffle_epi32(r1Niv,_MM_PERM_DDDD);store256(st_1+p,rt);for(idti=0;i<L;++i){autoconstp0=f+j+_itth-l+i,p1=p0+L,p2=p1+L,p3=p2+L;constautof0=load256(p0),f1=load256(p1),f2=load256(p2),f3=load256(p3);constautog0=add32(f0,f1,Mod2),g1=sub32(f0,f1,Mod2);constautog2=add32(f2,f3,Mod2),g3=mul_bsmfxd(Lsub32(f3,f2,Mod2),Img,ImgNiv,Mod);constautoh0=Ladd32(g0,g2,Mod2),h1=Ladd32(g1,g3,Mod2);constautoh2=Lsub32(g0,g2,Mod2),h3=Lsub32(g1,g3,Mod2);constautou0=shrk32(h0,Mod2),u1=mul_bsmfxd(h1,r1,r1Niv,Mod);constautou2=mul_bsmfxd(h2,r2,r2Niv,Mod),u3=mul_bsmfxd(h3,r3,r3Niv,Mod);store256(p0,u0),store256(p1,u1),store256(p2,u2),store256(p3,u3);}}}}if(shrk&&nn==n&&n<=_itth){for(idti=0;i<n;++i){constautof0=load256(f+i);store256(f+i,shrk32(f0,Mod));}}if(nn!=n){for(idti=0;i<nn;++i){autoconstp0=f+i,p1=f+nn+i;constautof0=load256(p0),f1=load256(p1);constautog0=add32(f0,f1,Mod2),g1=sub32(f0,f1,Mod2);ifconstexpr(shrk){constautoh0=shrk32(g0,Mod),h1=shrk32(g1,Mod);store256(p0,h0),store256(p1,h1);}else{store256(p0,g0),store256(p1,g1);}}}}// Returns fx * f[0,8) * g[0,8) (mod x^8 - ww).[[gnu::always_inline]]inlineI256convolve8(constI256*f,constI256*g,I256ww,I256fx,I256Niv,I256Mod,I256Mod2){constautoraa=load256(f),rbb=load256(g);constautotaa=shrk32(raa,Mod2),bb=shrk32(mul_bsm(rbb,fx,Niv,Mod),Mod);constautoaw=shrk32(mul_bsm(taa,ww,Niv,Mod),Mod);constautoaa=shrk32(taa,Mod);constautoawa=_mm256_permute2x128_si256(aa,aw,3);constautob0=_mm256_permute4x64_epi64(bb,0x00),b1=_mm256_shuffle_epi32(b0,_MM_PERM_CDAB);constautoa0=aa,a1=_mm256_srli_epi64(a0,32);constautoaw7=_mm256_alignr_epi8(aa,awa,12);autores00=_mm256_mul_epu32(a0,b0);autores01=_mm256_mul_epu32(a1,b0);autores10=_mm256_mul_epu32(aw7,b1);autores11=_mm256_mul_epu32(a0,b1);constautob2=_mm256_permute4x64_epi64(bb,0x55),b3=_mm256_shuffle_epi32(b2,_MM_PERM_CDAB);constautoaw6=_mm256_alignr_epi8(aa,awa,8);constautoaw5=_mm256_alignr_epi8(aa,awa,4);res00=_mm256_add_epi64(res00,_mm256_mul_epu32(aw6,b2));res01=_mm256_add_epi64(res01,_mm256_mul_epu32(aw7,b2));res10=_mm256_add_epi64(res10,_mm256_mul_epu32(aw5,b3));res11=_mm256_add_epi64(res11,_mm256_mul_epu32(aw6,b3));constautob4=_mm256_permute4x64_epi64(bb,0xaa),b5=_mm256_shuffle_epi32(b4,_MM_PERM_CDAB);constautoaw3=_mm256_alignr_epi8(awa,aw,12);res00=_mm256_add_epi64(res00,_mm256_mul_epu32(awa,b4));res01=_mm256_add_epi64(res01,_mm256_mul_epu32(aw5,b4));res10=_mm256_add_epi64(res10,_mm256_mul_epu32(aw3,b5));res11=_mm256_add_epi64(res11,_mm256_mul_epu32(awa,b5));constautob6=_mm256_permute4x64_epi64(bb,0xff),b7=_mm256_shuffle_epi32(b6,_MM_PERM_CDAB);constautoaw2=_mm256_alignr_epi8(awa,aw,8);constautoaw1=_mm256_alignr_epi8(awa,aw,4);res00=_mm256_add_epi64(res00,_mm256_mul_epu32(aw2,b6));res01=_mm256_add_epi64(res01,_mm256_mul_epu32(aw3,b6));res10=_mm256_add_epi64(res10,_mm256_mul_epu32(aw1,b7));res11=_mm256_add_epi64(res11,_mm256_mul_epu32(aw2,b7));res00=_mm256_add_epi64(res00,res10);res01=_mm256_add_epi64(res01,res11);returnshrk32(reduce(res00,res01,Niv,Mod),Mod2);}inlinevoidvector_convolution_direct(I256*f,constI256*g,idtlm,constFNTT32_info*constinfo){u32RR=info->one;constautomod=info->mod,niv=info->niv;constautoFx=_mm256_set1_epi32(mul_s((mod-((mod-1)>>(__builtin_ctzll(lm)))),info->r3,niv,mod));constautoNiv=_mm256_set1_epi32(niv),Mod=_mm256_set1_epi32(mod),Mod2=_mm256_set1_epi32(info->mod2);for(idti=0;i<lm;++i){store256(f+i,convolve8(f+i,g+i,_mm256_set1_epi32(RR),Fx,Niv,Mod,Mod2));RR=mul(RR,info->RT1[__builtin_ctzll(~i)],niv,mod);}}inlinevoidvector_convolution_accumulate(I256*constresult,constI256*constf,constI256*constg,idtlm,constFNTT32_info*constinfo){u32RR=info->one;constautomod=info->mod,niv=info->niv;constautoFx=_mm256_set1_epi32(mul_s((mod-((mod-1)>>(__builtin_ctzll(lm)))),info->r3,niv,mod));constautoNiv=_mm256_set1_epi32(niv),Mod=_mm256_set1_epi32(mod),Mod2=_mm256_set1_epi32(info->mod2);for(idti=0;i<lm;++i){constautoproduct=convolve8(f+i,g+i,_mm256_set1_epi32(RR),Fx,Niv,Mod,Mod2);store256(result+i,add32(load256(result+i),product,Mod2));RR=mul(RR,info->RT1[__builtin_ctzll(~i)],niv,mod);}}}// namespace fast998_v2}// namespace internal}// namespace fps}// namespace m1une#endif // M1UNE_FPS_HAS_X86_SIMD
#line 24 "math/fps/convolution.hpp"
#ifdef M1UNE_FPS_HAS_X86_SIMD
#pragma GCC pop_options
#endif
#line 1 "math/modint.hpp"
#line 6 "math/modint.hpp"
#include<iostream>
#line 9 "math/modint.hpp"
namespacem1une{namespacemath{template<uint32_tModulus>structModInt{static_assert(0<Modulus,"Modulus must be positive");private:uint32_t_v;public:staticconstexpruint32_tmod(){returnModulus;}staticconstexprModIntraw(uint32_tv)noexcept{ModIntx;x._v=v;returnx;}constexprModInt()noexcept:_v(0){}template<classInteger,std::enable_if_t<std::is_integral_v<Integer>,int>=0>constexprModInt(Integerv)noexcept{ifconstexpr(std::is_signed_v<Integer>){int64_tx=static_cast<int64_t>(v)%static_cast<int64_t>(Modulus);if(x<0)x+=Modulus;_v=static_cast<uint32_t>(x);}else{_v=static_cast<uint32_t>(static_cast<uint64_t>(v)%Modulus);}}constexpruint32_tval()constnoexcept{return_v;}constexprModInt&operator++()noexcept{_v++;if(_v==Modulus)_v=0;return*this;}constexprModInt&operator--()noexcept{if(_v==0)_v=Modulus;_v--;return*this;}constexprModIntoperator++(int)noexcept{ModIntres=*this;++*this;returnres;}constexprModIntoperator--(int)noexcept{ModIntres=*this;--*this;returnres;}constexprModInt&operator+=(constModInt&rhs)noexcept{_v+=rhs._v;if(_v>=Modulus)_v-=Modulus;return*this;}constexprModInt&operator-=(constModInt&rhs)noexcept{_v-=rhs._v;if(_v>=Modulus)_v+=Modulus;return*this;}constexprModInt&operator*=(constModInt&rhs)noexcept{uint64_tz=_v;z*=rhs._v;_v=static_cast<uint32_t>(z%Modulus);return*this;}constexprModInt&operator/=(constModInt&rhs)noexcept{return*this*=rhs.inv();}constexprModIntoperator+(constModInt&rhs)constnoexcept{returnModInt(*this)+=rhs;}constexprModIntoperator-(constModInt&rhs)constnoexcept{returnModInt(*this)-=rhs;}constexprModIntoperator*(constModInt&rhs)constnoexcept{returnModInt(*this)*=rhs;}constexprModIntoperator/(constModInt&rhs)constnoexcept{returnModInt(*this)/=rhs;}constexprbooloperator==(constModInt&rhs)constnoexcept{return_v==rhs._v;}constexprbooloperator!=(constModInt&rhs)constnoexcept{return_v!=rhs._v;}constexprModIntpow(longlongn)constnoexcept{ModIntres=raw(1%Modulus);ModIntx=n<0?inv():*this;uint64_texponent=n<0?uint64_t(-(n+1))+1:uint64_t(n);while(exponent>0){if(exponent&1)res*=x;x*=x;exponent>>=1;}returnres;}constexprModIntinv()constnoexcept{int64_ta=_v,b=Modulus,u=1,v=0;while(b){int64_tt=a/b;a-=t*b;std::swap(a,b);u-=t*v;std::swap(u,v);}assert(a==1);u%=Modulus;if(u<0)u+=Modulus;returnraw(static_cast<uint32_t>(u));}friendstd::ostream&operator<<(std::ostream&os,constModInt&rhs){returnos<<rhs._v;}friendstd::istream&operator>>(std::istream&is,ModInt&rhs){longlongv;is>>v;rhs=ModInt(v);returnis;}};usingmodint998244353=ModInt<998244353>;usingmodint1000000007=ModInt<1000000007>;template<intId=0>structDynamicModInt{private:uint32_t_v;inlinestaticuint32_t_mod=1;public:staticuint32_tmod()noexcept{return_mod;}staticvoidset_mod(uint32_tmodulus)noexcept{assert(modulus>0);assert(modulus<=uint32_t(1)<<31);_mod=modulus;}staticDynamicModIntraw(uint32_tv)noexcept{assert(v<_mod);DynamicModIntx;x._v=v;returnx;}DynamicModInt()noexcept:_v(0){}template<classInteger,std::enable_if_t<std::is_integral_v<Integer>,int>=0>DynamicModInt(Integerv)noexcept{ifconstexpr(std::is_signed_v<Integer>){int64_tx=static_cast<int64_t>(v)%static_cast<int64_t>(_mod);if(x<0)x+=_mod;_v=static_cast<uint32_t>(x);}else{_v=static_cast<uint32_t>(static_cast<uint64_t>(v)%_mod);}}uint32_tval()constnoexcept{return_v;}DynamicModInt&operator++()noexcept{_v++;if(_v==_mod)_v=0;return*this;}DynamicModInt&operator--()noexcept{if(_v==0)_v=_mod;_v--;return*this;}DynamicModIntoperator++(int)noexcept{DynamicModIntresult=*this;++*this;returnresult;}DynamicModIntoperator--(int)noexcept{DynamicModIntresult=*this;--*this;returnresult;}DynamicModInt&operator+=(constDynamicModInt&rhs)noexcept{_v+=rhs._v;if(_v>=_mod)_v-=_mod;return*this;}DynamicModInt&operator-=(constDynamicModInt&rhs)noexcept{_v-=rhs._v;if(_v>=_mod)_v+=_mod;return*this;}DynamicModInt&operator*=(constDynamicModInt&rhs)noexcept{_v=static_cast<uint32_t>(uint64_t(_v)*rhs._v%_mod);return*this;}DynamicModInt&operator/=(constDynamicModInt&rhs)noexcept{return*this*=rhs.inv();}DynamicModIntoperator+(constDynamicModInt&rhs)constnoexcept{returnDynamicModInt(*this)+=rhs;}DynamicModIntoperator-(constDynamicModInt&rhs)constnoexcept{returnDynamicModInt(*this)-=rhs;}DynamicModIntoperator*(constDynamicModInt&rhs)constnoexcept{returnDynamicModInt(*this)*=rhs;}DynamicModIntoperator/(constDynamicModInt&rhs)constnoexcept{returnDynamicModInt(*this)/=rhs;}booloperator==(constDynamicModInt&rhs)constnoexcept{return_v==rhs._v;}booloperator!=(constDynamicModInt&rhs)constnoexcept{return_v!=rhs._v;}DynamicModIntpow(longlongexponent)constnoexcept{DynamicModIntresult=raw(1%_mod);DynamicModIntbase=exponent<0?inv():*this;uint64_tmagnitude=exponent<0?uint64_t(-(exponent+1))+1:uint64_t(exponent);while(magnitude>0){if(magnitude&1)result*=base;base*=base;magnitude>>=1;}returnresult;}DynamicModIntinv()constnoexcept{int64_ta=_v,b=_mod,u=1,v=0;while(b){int64_tquotient=a/b;a-=quotient*b;std::swap(a,b);u-=quotient*v;std::swap(u,v);}assert(a==1);u%=_mod;if(u<0)u+=_mod;returnraw(static_cast<uint32_t>(u));}friendstd::ostream&operator<<(std::ostream&os,constDynamicModInt&rhs){returnos<<rhs._v;}friendstd::istream&operator>>(std::istream&is,DynamicModInt&rhs){longlongvalue;is>>value;rhs=DynamicModInt(value);returnis;}};}// namespace math}// namespace m1une#line 29 "math/fps/convolution.hpp"
namespacem1une{namespacefps{namespaceinternal{template<classMint,class=void>structhas_static_modulus:std::false_type{};template<classMint>structhas_static_modulus<Mint,std::void_t<decltype(std::integral_constant<uint32_t,Mint::mod()>{})>>:std::true_type{};constexpruint32_tprimitive_root_constexpr(uint32_tmod){if(mod==2)return1;if(mod==167772161)return3;if(mod==469762049)return3;if(mod==754974721)return11;if(mod==998244353)return3;if(mod==1224736769)return3;uint32_tdivisors[32]={};intcount=0;uint32_tx=mod-1;for(uint32_tp=2;uint64_t(p)*p<=x;p++){if(x%p!=0)continue;divisors[count++]=p;while(x%p==0)x/=p;}if(x>1)divisors[count++]=x;for(uint32_tg=2;;g++){boolok=true;for(inti=0;i<count;i++){uint64_tvalue=1;uint64_tbase=g;uint32_texponent=(mod-1)/divisors[i];while(exponent>0){if(exponent&1)value=value*base%mod;base=base*base%mod;exponent>>=1;}if(value==1){ok=false;break;}}if(ok)returng;}}constexprinttwo_adic_order(uint32_tx){intresult=0;while((x&1)==0){x>>=1;result++;}returnresult;}template<classMint>structNttRoots{staticconstexprintmax_base=two_adic_order(Mint::mod()-1);std::array<Mint,max_base+1>root;std::array<Mint,max_base+1>inverse_root;std::array<Mint,max_base>rate;std::array<Mint,max_base>inverse_rate;std::array<Mint,max_base>rate_radix4;std::array<Mint,max_base>inverse_rate_radix4;NttRoots(){constexpruint32_tprimitive_root=primitive_root_constexpr(Mint::mod());for(intlevel=1;level<=max_base;level++){root[level]=Mint(primitive_root).pow((Mint::mod()-1)>>level);inverse_root[level]=root[level].inv();}Mintproduct=1;Mintinverse_product=1;for(inti=0;i+1<max_base;i++){rate[i]=root[i+2]*product;inverse_rate[i]=inverse_root[i+2]*inverse_product;product*=inverse_root[i+2];inverse_product*=root[i+2];}product=1;inverse_product=1;for(inti=0;i+2<max_base;i++){rate_radix4[i]=root[i+3]*product;inverse_rate_radix4[i]=inverse_root[i+3]*inverse_product;product*=inverse_root[i+3];inverse_product*=root[i+3];}}};template<classMint>constNttRoots<Mint>&ntt_roots(){staticconstNttRoots<Mint>roots;returnroots;}template<classMint>voidntt(std::vector<Mint>&a,boolinverse,boolnormalize=true){constintn=int(a.size());assert(n>0&&(n&(n-1))==0);assert((Mint::mod()-1)%uint32_t(n)==0);constauto&roots=ntt_roots<Mint>();constintheight=two_adic_order(uint32_t(n));if(!inverse){intphase=0;while(phase<height){if(height-phase==1){constintwidth=1<<(height-phase-1);Minttwiddle=1;for(intblock=0;block<(1<<phase);block++){constintoffset=block<<(height-phase);for(inti=0;i<width;i++){constMintleft=a[offset+i];constMintright=a[offset+i+width]*twiddle;a[offset+i]=left+right;a[offset+i+width]=left-right;}if(block+1!=(1<<phase))twiddle*=roots.rate[__builtin_ctz(~uint32_t(block))];}phase++;continue;}constintwidth=1<<(height-phase-2);Minttwiddle=1;constMintimaginary=roots.root[2];for(intblock=0;block<(1<<phase);block++){constMinttwiddle2=twiddle*twiddle;constMinttwiddle3=twiddle2*twiddle;constintoffset=block<<(height-phase);for(inti=0;i<width;i++){constuint64_tmod2=uint64_t(Mint::mod())*Mint::mod();constuint64_ta0=a[offset+i].val();constuint64_ta1=uint64_t(a[offset+i+width].val())*twiddle.val();constuint64_ta2=uint64_t(a[offset+i+2*width].val())*twiddle2.val();constuint64_ta3=uint64_t(a[offset+i+3*width].val())*twiddle3.val();constuint64_ta1na3i=uint64_t(Mint(a1+mod2-a3).val())*imaginary.val();constuint64_tnegative_a2=mod2-a2;a[offset+i]=Mint(a0+a2+a1+a3);a[offset+i+width]=Mint(a0+a2+2*mod2-a1-a3);a[offset+i+2*width]=Mint(a0+negative_a2+a1na3i);a[offset+i+3*width]=Mint(a0+negative_a2+mod2-a1na3i);}if(block+1!=(1<<phase))twiddle*=roots.rate_radix4[__builtin_ctz(~uint32_t(block))];}phase+=2;}}else{intphase=height;while(phase>0){if(phase==1){constintwidth=1<<(height-phase);Minttwiddle=1;for(intblock=0;block<(1<<(phase-1));block++){constintoffset=block<<(height-phase+1);for(inti=0;i<width;i++){constMintleft=a[offset+i];constMintright=a[offset+i+width];a[offset+i]=left+right;a[offset+i+width]=(left-right)*twiddle;}if(block+1!=(1<<(phase-1)))twiddle*=roots.inverse_rate[__builtin_ctz(~uint32_t(block))];}phase--;continue;}constintwidth=1<<(height-phase);Minttwiddle=1;constMintinverse_imaginary=roots.inverse_root[2];for(intblock=0;block<(1<<(phase-2));block++){constMinttwiddle2=twiddle*twiddle;constMinttwiddle3=twiddle2*twiddle;constintoffset=block<<(height-phase+2);for(inti=0;i<width;i++){constuint64_ta0=a[offset+i].val();constuint64_ta1=a[offset+i+width].val();constuint64_ta2=a[offset+i+2*width].val();constuint64_ta3=a[offset+i+3*width].val();constuint64_ta2na3i=uint64_t(Mint((Mint::mod()+a2-a3)*inverse_imaginary.val()).val());a[offset+i]=Mint(a0+a1+a2+a3);a[offset+i+width]=Mint((a0+Mint::mod()-a1+a2na3i)*twiddle.val());a[offset+i+2*width]=Mint((a0+a1+2ULL*Mint::mod()-a2-a3)*twiddle2.val());a[offset+i+3*width]=Mint((a0+Mint::mod()-a1+Mint::mod()-a2na3i)*twiddle3.val());}if(block+1!=(1<<(phase-2)))twiddle*=roots.inverse_rate_radix4[__builtin_ctz(~uint32_t(block))];}phase-=2;}if(normalize){constMintinverse_n=Mint(n).inv();for(Mint&value:a)value*=inverse_n;}}}#ifdef M1UNE_FPS_HAS_X86_SIMD
#pragma GCC push_options
#pragma GCC target("avx2,bmi")
template<classMint>__attribute__((target("avx2,bmi"),hot))std::vector<Mint>convolution_998244353_simd(conststd::vector<Mint>&a,conststd::vector<Mint>&b){constintresult_size=int(a.size()+b.size()-1);intn=1;while(n<result_size)n<<=1;constboolsquaring=&a==&b;auto*transformed_a=static_cast<uint32_t*>(::operatornew[](sizeof(uint32_t)*n,std::align_val_t(32)));auto*transformed_b=squaring?transformed_a:static_cast<uint32_t*>(::operatornew[](sizeof(uint32_t)*n,std::align_val_t(32)));ifconstexpr(std::is_same_v<Mint,math::ModInt<998244353>>){static_assert(sizeof(Mint)==sizeof(uint32_t)&&std::is_trivially_copyable_v<Mint>);std::memcpy(transformed_a,a.data(),sizeof(uint32_t)*a.size());if(!squaring)std::memcpy(transformed_b,b.data(),sizeof(uint32_t)*b.size());}else{for(inti=0;i<int(a.size());i++)transformed_a[i]=a[i].val();if(!squaring)for(inti=0;i<int(b.size());i++)transformed_b[i]=b[i].val();}std::memset(transformed_a+a.size(),0,sizeof(uint32_t)*(n-a.size()));if(!squaring)std::memset(transformed_b+b.size(),0,sizeof(uint32_t)*(n-b.size()));staticconstexprfast998_v2::FNTT32_infotransform(998244353);conststd::size_tvector_size=std::size_t(n)>>3;fast998_v2::vector_dif(reinterpret_cast<__m256i*>(transformed_a),vector_size,&transform);if(!squaring)fast998_v2::vector_dif(reinterpret_cast<__m256i*>(transformed_b),vector_size,&transform);fast998_v2::vector_convolution_direct(reinterpret_cast<__m256i*>(transformed_a),reinterpret_cast<const__m256i*>(transformed_b),vector_size,&transform);fast998_v2::vector_dit<true>(reinterpret_cast<__m256i*>(transformed_a),vector_size,&transform);std::vector<Mint>result(result_size);for(intj=0;j<result_size;j++)result[j]=Mint::raw(transformed_a[j]);::operatordelete[](transformed_a,std::align_val_t(32));if(!squaring)::operatordelete[](transformed_b,std::align_val_t(32));returnresult;}#pragma GCC pop_options
#endif
}// namespace internaltemplate<classMint>std::vector<Mint>convolution_naive(conststd::vector<Mint>&a,conststd::vector<Mint>&b){if(a.empty()||b.empty())return{};std::vector<Mint>result(a.size()+b.size()-1);if(a.size()<b.size()){for(inti=0;i<int(a.size());i++){for(intj=0;j<int(b.size());j++)result[i+j]+=a[i]*b[j];}}else{for(intj=0;j<int(b.size());j++){for(inti=0;i<int(a.size());i++)result[i+j]+=a[i]*b[j];}}returnresult;}template<classMint>std::vector<Mint>convolution_ntt(conststd::vector<Mint>&a,conststd::vector<Mint>&b){constintresult_size=int(a.size()+b.size()-1);intn=1;while(n<result_size)n<<=1;assert((Mint::mod()-1)%uint32_t(n)==0);#ifdef M1UNE_FPS_HAS_X86_SIMD
ifconstexpr(Mint::mod()==998244353){if(n>=64&&__builtin_cpu_supports("avx2"))returninternal::convolution_998244353_simd(a,b);}#endif
// Allocate the padded buffers directly. Constructing from the inputs and// then resizing used to allocate and copy both large operands twice.constboolsquaring=&a==&b;std::vector<Mint>fa(n);std::copy(a.begin(),a.end(),fa.begin());internal::ntt(fa,false);constMintinverse_n=Mint(n).inv();if(squaring){for(inti=0;i<n;i++)fa[i]*=fa[i]*inverse_n;}else{std::vector<Mint>fb(n);std::copy(b.begin(),b.end(),fb.begin());internal::ntt(fb,false);for(inti=0;i<n;i++)fa[i]*=fb[i]*inverse_n;}internal::ntt(fa,true,false);fa.resize(result_size);returnfa;}namespaceinternal{template<classMint>std::vector<Mint>convolution_998244353_blocked_scalar(conststd::vector<Mint>&a,conststd::vector<Mint>&b,inttransform_size){assert(Mint::mod()==998244353);assert(transform_size>=2&&(transform_size&(transform_size-1))==0);assert((Mint::mod()-1)%uint32_t(transform_size)==0);constintblock_size=transform_size/2;constinta_blocks=int((a.size()+block_size-1)/block_size);constintb_blocks=int((b.size()+block_size-1)/block_size);autotransform_blocks=[&](conststd::vector<Mint>&values,intblock_count){std::vector<std::vector<Mint>>blocks;blocks.reserve(block_count);for(intblock=0;block<block_count;block++){constintbegin=block*block_size;constintcount=std::min(block_size,int(values.size())-begin);std::vector<Mint>transformed(transform_size);std::copy_n(values.begin()+begin,count,transformed.begin());ntt(transformed,false);blocks.emplace_back(std::move(transformed));}returnblocks;};std::vector<std::vector<Mint>>transformed_a=transform_blocks(a,a_blocks);std::vector<std::vector<Mint>>transformed_b=transform_blocks(b,b_blocks);constintresult_size=int(a.size()+b.size()-1);std::vector<Mint>result(result_size);std::vector<Mint>transformed_result(transform_size);for(intdiagonal=0;diagonal<a_blocks+b_blocks-1;diagonal++){std::fill(transformed_result.begin(),transformed_result.end(),Mint(0));constintfirst_a=std::max(0,diagonal-(b_blocks-1));constintlast_a=std::min(a_blocks-1,diagonal);for(inta_block=first_a;a_block<=last_a;a_block++){constintb_block=diagonal-a_block;for(inti=0;i<transform_size;i++)transformed_result[i]+=transformed_a[a_block][i]*transformed_b[b_block][i];}ntt(transformed_result,true);constintoutput_offset=diagonal*block_size;constintoutput_count=std::min(transform_size,result_size-output_offset);for(inti=0;i<output_count;i++)result[output_offset+i]+=transformed_result[i];}returnresult;}#ifdef M1UNE_FPS_HAS_X86_SIMD
classAlignedUint32Buffer{private:uint32_t*data_;public:explicitAlignedUint32Buffer(std::size_tsize):data_(static_cast<uint32_t*>(::operatornew[](sizeof(uint32_t)*size,std::align_val_t(32)))){}AlignedUint32Buffer(constAlignedUint32Buffer&)=delete;AlignedUint32Buffer&operator=(constAlignedUint32Buffer&)=delete;AlignedUint32Buffer(AlignedUint32Buffer&&other)noexcept:data_(other.data_){other.data_=nullptr;}AlignedUint32Buffer&operator=(AlignedUint32Buffer&&other)noexcept{if(this==&other)return*this;::operatordelete[](data_,std::align_val_t(32));data_=other.data_;other.data_=nullptr;return*this;}~AlignedUint32Buffer(){::operatordelete[](data_,std::align_val_t(32));}uint32_t*data(){returndata_;}constuint32_t*data()const{returndata_;}};template<classMint>__attribute__((target("avx2,bmi"),hot))std::vector<Mint>convolution_998244353_blocked_simd(conststd::vector<Mint>&a,conststd::vector<Mint>&b,inttransform_size){assert(Mint::mod()==998244353);assert(transform_size>=64&&(transform_size&(transform_size-1))==0);assert((Mint::mod()-1)%uint32_t(transform_size)==0);constintblock_size=transform_size/2;constinta_blocks=int((a.size()+block_size-1)/block_size);constintb_blocks=int((b.size()+block_size-1)/block_size);staticconstexprfast998_v2::FNTT32_infotransform(998244353);conststd::size_tvector_size=std::size_t(transform_size)/8;autotransform_blocks=[&](conststd::vector<Mint>&values,intblock_count){std::vector<AlignedUint32Buffer>blocks;blocks.reserve(block_count);for(intblock=0;block<block_count;block++){constintbegin=block*block_size;constintcount=std::min(block_size,int(values.size())-begin);AlignedUint32Buffertransformed(transform_size);ifconstexpr(std::is_same_v<Mint,math::ModInt<998244353>>){static_assert(sizeof(Mint)==sizeof(uint32_t)&&std::is_trivially_copyable_v<Mint>);std::memcpy(transformed.data(),values.data()+begin,sizeof(uint32_t)*count);}else{for(inti=0;i<count;i++)transformed.data()[i]=values[begin+i].val();}std::memset(transformed.data()+count,0,sizeof(uint32_t)*(transform_size-count));fast998_v2::vector_dif(reinterpret_cast<__m256i*>(transformed.data()),vector_size,&transform);blocks.emplace_back(std::move(transformed));}returnblocks;};std::vector<AlignedUint32Buffer>transformed_a=transform_blocks(a,a_blocks);std::vector<AlignedUint32Buffer>transformed_b=transform_blocks(b,b_blocks);constintresult_size=int(a.size()+b.size()-1);std::vector<Mint>result(result_size);AlignedUint32Buffertransformed_result(transform_size);for(intdiagonal=0;diagonal<a_blocks+b_blocks-1;diagonal++){std::memset(transformed_result.data(),0,sizeof(uint32_t)*transform_size);constintfirst_a=std::max(0,diagonal-(b_blocks-1));constintlast_a=std::min(a_blocks-1,diagonal);for(inta_block=first_a;a_block<=last_a;a_block++){constintb_block=diagonal-a_block;fast998_v2::vector_convolution_accumulate(reinterpret_cast<__m256i*>(transformed_result.data()),reinterpret_cast<const__m256i*>(transformed_a[a_block].data()),reinterpret_cast<const__m256i*>(transformed_b[b_block].data()),vector_size,&transform);}fast998_v2::vector_dit<true>(reinterpret_cast<__m256i*>(transformed_result.data()),vector_size,&transform);constintoutput_offset=diagonal*block_size;constintoutput_count=std::min(transform_size,result_size-output_offset);for(inti=0;i<output_count;i++){uint32_tvalue=result[output_offset+i].val()+transformed_result.data()[i];if(value>=Mint::mod())value-=Mint::mod();result[output_offset+i]=Mint::raw(value);}}returnresult;}#endif
template<classMint>std::vector<Mint>convolution_998244353_blocked(conststd::vector<Mint>&a,conststd::vector<Mint>&b,inttransform_size=1<<23){#ifdef M1UNE_FPS_HAS_X86_SIMD
if(transform_size>=64&&__builtin_cpu_supports("avx2"))returnconvolution_998244353_blocked_simd(a,b,transform_size);#endif
returnconvolution_998244353_blocked_scalar(a,b,transform_size);}}// namespace internaltemplate<classMint>std::vector<Mint>convolution(conststd::vector<Mint>&a,conststd::vector<Mint>&b){if(a.empty()||b.empty())return{};if(std::min(a.size(),b.size())<=32)returnconvolution_naive(a,b);constintresult_size=int(a.size()+b.size()-1);intn=1;while(n<result_size)n<<=1;ifconstexpr(internal::has_static_modulus<Mint>::value){ifconstexpr(Mint::mod()==998244353){if(n>(1<<23))returninternal::convolution_998244353_blocked(a,b);}if((Mint::mod()-1)%uint32_t(n)==0)returnconvolution_ntt(a,b);}usingMint1=math::ModInt<167772161>;usingMint2=math::ModInt<469762049>;usingMint3=math::ModInt<754974721>;assert(n<=(1<<24));[[maybe_unused]]constunsigned__int128coefficient_bound=static_cast<unsigned__int128>(std::min(a.size(),b.size()))*(Mint::mod()-1)*(Mint::mod()-1);[[maybe_unused]]constunsigned__int128crt_modulus=static_cast<unsigned__int128>(Mint1::mod())*Mint2::mod()*Mint3::mod();assert(coefficient_bound<crt_modulus);autoconverted_convolution=[&]<classOtherMint>(){std::vector<OtherMint>converted_a(a.size());std::vector<OtherMint>converted_b(b.size());for(inti=0;i<int(a.size());i++)converted_a[i]=OtherMint(a[i].val());for(inti=0;i<int(b.size());i++)converted_b[i]=OtherMint(b[i].val());returnconvolution_ntt(converted_a,converted_b);};std::vector<Mint1>c1=converted_convolution.templateoperator()<Mint1>();std::vector<Mint2>c2=converted_convolution.templateoperator()<Mint2>();std::vector<Mint3>c3=converted_convolution.templateoperator()<Mint3>();staticconstuint64_tinverse_mod1_mod2=Mint2(Mint1::mod()).inv().val();staticconstuint64_tmod1_mod3=Mint1::mod()%Mint3::mod();staticconstuint64_tmod1_mod2_mod3=mod1_mod3*(Mint2::mod()%Mint3::mod())%Mint3::mod();staticconstuint64_tinverse_mod1_mod2_mod3=Mint3(uint32_t(mod1_mod2_mod3)).inv().val();constuint64_ttarget_mod=Mint::mod();constuint64_tmod1_target=Mint1::mod()%target_mod;constuint64_tmod1_mod2_target=mod1_target*(Mint2::mod()%target_mod)%target_mod;std::vector<Mint>result(result_size);for(inti=0;i<result_size;i++){constuint64_tr1=c1[i].val();constuint64_tr2=c2[i].val();constuint64_tr3=c3[i].val();constuint64_tfirst=(r2+Mint2::mod()-r1%Mint2::mod())%Mint2::mod()*inverse_mod1_mod2%Mint2::mod();constuint64_tcombined_mod3=(r1%Mint3::mod()+mod1_mod3*(first%Mint3::mod()))%Mint3::mod();constuint64_tsecond=(r3+Mint3::mod()-combined_mod3)%Mint3::mod()*inverse_mod1_mod2_mod3%Mint3::mod();uint64_tvalue=r1%target_mod;value=(value+mod1_target*(first%target_mod))%target_mod;value=(value+mod1_mod2_target*(second%target_mod))%target_mod;result[i]=Mint::raw(uint32_t(value));}returnresult;}}// namespace fps}// namespace m1une#ifdef M1UNE_FPS_HAS_X86_SIMD
#undef M1UNE_FPS_HAS_X86_SIMD
#endif
#line 9 "string/wildcard_pattern_matching.hpp"
namespacem1une{namespacestring{namespaceinternal{template<classMint>std::vector<Mint>wildcard_mismatch_scores(conststd::string&text,conststd::string&pattern,charwildcard){intn=int(text.size());intm=int(pattern.size());std::array<std::vector<Mint>,3>text_powers;std::array<std::vector<Mint>,3>pattern_powers;for(auto&powers:text_powers)powers.resize(n);for(auto&powers:pattern_powers)powers.resize(m);autoencode=[wildcard](charcharacter){if(character==wildcard)return0;returnint(static_cast<unsignedchar>(character))+1;};for(inti=0;i<n;i++){Mintvalue=encode(text[i]);text_powers[0][i]=value;text_powers[1][i]=value*value;text_powers[2][i]=value*value*value;}for(inti=0;i<m;i++){Mintvalue=encode(pattern[m-1-i]);pattern_powers[0][i]=value;pattern_powers[1][i]=value*value;pattern_powers[2][i]=value*value*value;}std::vector<Mint>scores(n-m+1);for(intpower=0;power<3;power++){std::vector<Mint>product=fps::convolution(text_powers[power],pattern_powers[2-power]);Mintmultiplier=power==1?Mint(-2):Mint(1);for(intstart=0;start<=n-m;start++){scores[start]+=multiplier*product[start+m-1];}}returnscores;}}// namespace internal// result[i] is true exactly when pattern matches text[i, i + pattern.size()).// The wildcard character matches every character on either side.inlinestd::vector<bool>wildcard_pattern_matching(conststd::string&text,conststd::string&pattern,charwildcard='*'){intn=int(text.size());intm=int(pattern.size());if(m==0)returnstd::vector<bool>(n+1,true);if(n<m)return{};usingMint1=math::ModInt<469762049>;usingMint2=math::ModInt<754974721>;std::vector<Mint1>first_scores=internal::wildcard_mismatch_scores<Mint1>(text,pattern,wildcard);std::vector<Mint2>second_scores=internal::wildcard_mismatch_scores<Mint2>(text,pattern,wildcard);std::vector<bool>result(n-m+1,false);for(intstart=0;start<=n-m;start++){result[start]=first_scores[start].val()==0&&second_scores[start].val()==0;}returnresult;}}// namespace string}// namespace m1une#line 1 "string/z_algorithm.hpp"
#line 6 "string/z_algorithm.hpp"
namespacem1une{namespacestring{// Returns z[i] = LCP(sequence, sequence[i..]).template<classSequence>std::vector<int>z_algorithm(constSequence&sequence){intn=int(sequence.size());if(n==0)return{};std::vector<int>z(n);z[0]=n;intleft=0;intright=0;for(inti=1;i<n;i++){if(i<right)z[i]=std::min(right-i,z[i-left]);while(i+z[i]<n&&sequence[z[i]]==sequence[i+z[i]]){z[i]++;}if(right<i+z[i]){left=i;right=i+z[i];}}returnz;}}// namespace string}// namespace m1une#line 27 "string/all.hpp"
#line 4 "verify/string/string_algorithms.test.cpp"
#line 1 "utilities/fast_io.hpp"
#line 6 "utilities/fast_io.hpp"
#include<cerrno>
#include<charconv>
#line 9 "utilities/fast_io.hpp"
#include<cstdio>
#include<cstdlib>
#line 13 "utilities/fast_io.hpp"
#include<iterator>
#line 15 "utilities/fast_io.hpp"
#include<sys/stat.h>
#line 18 "utilities/fast_io.hpp"
#include<unistd.h>
#line 20 "utilities/fast_io.hpp"
namespacem1une{namespaceutilities{structFastOutput;namespaceinternal{// Shared with the convenience helpers in template.hpp.inlineFastOutput*standard_output_instance=nullptr;// Detect std::begin(x), std::end(x).template<classT,class=void>structis_range:std::false_type{};template<classT>structis_range<T,std::void_t<decltype(std::begin(std::declval<T&>())),decltype(std::end(std::declval<T&>()))>>:std::true_type{};template<classT>inlineconstexprboolis_range_v=is_range<T>::value;template<classT>usingrange_reference_t=decltype(*std::begin(std::declval<T&>()));template<classT>usingrange_value_t=std::remove_cv_t<std::remove_reference_t<range_reference_t<T>>>;template<classT,class=void>structrange_stored_value{usingtype=range_value_t<T>;};template<classT>structrange_stored_value<T,std::void_t<typenamestd::remove_cv_t<std::remove_reference_t<T>>::value_type>>{usingtype=typenamestd::remove_cv_t<std::remove_reference_t<T>>::value_type;};template<classT>usingrange_stored_value_t=typenamerange_stored_value<T>::type;// Treat strings and C strings as scalar output objects, not as ranges.template<classT>structis_char_array:std::false_type{};template<classT,std::size_tN>structis_char_array<T[N]>:std::bool_constant<std::is_same_v<std::remove_cv_t<T>,char>>{};template<classT>structis_string_like:std::bool_constant<std::is_same_v<std::decay_t<T>,std::string>||std::is_same_v<std::decay_t<T>,constchar*>||std::is_same_v<std::decay_t<T>,char*>||is_char_array<std::remove_reference_t<T>>::value>{};template<classT>inlineconstexprboolis_string_like_v=is_string_like<T>::value;// ModInt-like type: x.val() is printable, and x can be assigned from long long.template<classT,class=void>structhas_val_method:std::false_type{};template<classT>structhas_val_method<T,std::void_t<decltype(std::declval<constT&>().val())>>:std::true_type{};template<classT>inlineconstexprboolhas_val_method_v=has_val_method<T>::value;template<classT,class=void>structhas_static_mod_raw:std::false_type{};template<classT>structhas_static_mod_raw<T,std::void_t<decltype(T::mod()),decltype(T::raw(std::declval<uint32_t>()))>>:std::true_type{};template<classT>inlineconstexprboolhas_static_mod_raw_v=has_static_mod_raw<T>::value;// libstdc++ before GCC 16 does not classify __int128 as an integral type in// strict ISO modes such as -std=c++23. Keep the fast-I/O interface independent// of that implementation detail.template<classT>inlineconstexprboolis_integral_v=std::is_integral_v<T>||std::is_same_v<std::remove_cv_t<T>,__int128_t>||std::is_same_v<std::remove_cv_t<T>,__uint128_t>;template<classT>inlineconstexprboolis_signed_v=std::is_signed_v<T>||std::is_same_v<std::remove_cv_t<T>,__int128_t>;template<classT>structmake_unsigned{usingtype=std::make_unsigned_t<T>;};template<>structmake_unsigned<__int128_t>{usingtype=__uint128_t;};template<>structmake_unsigned<__uint128_t>{usingtype=__uint128_t;};template<classT>usingmake_unsigned_t=typenamemake_unsigned<std::remove_cv_t<T>>::type;}// namespace internalstructFastInput{staticconstexprintbuffer_size=1<<20;private:std::FILE*_stream;char_buffer[buffer_size];int_position;int_length;int_file_descriptor;bool_streaming;boolrefill(){_position=0;if(_streaming){ssize_tlength;do{length=::read(_file_descriptor,_buffer,buffer_size);}while(length<0&&errno==EINTR);if(length<=0){_length=0;returnfalse;}_length=int(length);}else{_length=int(std::fread(_buffer,1,buffer_size,_stream));}return_length!=0;}template<classT>boolread_integer_from_stream(T&value){if(!skip_spaces())returnfalse;intc=read_char_raw();boolnegative=false;if(c=='-'){negative=true;c=read_char_raw();}ifconstexpr(internal::is_signed_v<T>){Tresult=0;while('0'<=c&&c<='9'){result=negative?result*10-(c-'0'):result*10+(c-'0');c=read_char_raw();}value=result;}else{Tresult=0;while('0'<=c&&c<='9'){result=result*10+T(c-'0');c=read_char_raw();}value=negative?T(0)-result:result;}returntrue;}boolprepare_number(){if(_length-_position>=64)returntrue;constintremaining=_length-_position;if(remaining>0)std::memmove(_buffer,_buffer+_position,remaining);constintadded=int(std::fread(_buffer+remaining,1,buffer_size-remaining,_stream));_position=0;_length=remaining+added;if(_length<buffer_size)_buffer[_length]='\0';return_length!=0;}public:explicitFastInput(std::FILE*stream=stdin):_stream(stream),_position(0),_length(0),_file_descriptor(::fileno(stream)),_streaming([&]{structstatstatus;return_file_descriptor>=0&&::fstat(_file_descriptor,&status)==0&&!S_ISREG(status.st_mode);}()){}FastInput(constFastInput&)=delete;FastInput&operator=(constFastInput&)=delete;intread_char_raw(){if(_position==_length&&!refill())returnEOF;return_buffer[_position++];}boolskip_spaces(){intc=read_char_raw();while(c!=EOF&&c<=' ')c=read_char_raw();if(c==EOF)returnfalse;--_position;returntrue;}boolread(char&value){if(!skip_spaces())returnfalse;value=char(read_char_raw());returntrue;}boolread(std::string&value){if(!skip_spaces())returnfalse;value.clear();while(true){constintbegin=_position;while(_position<_length&&static_cast<unsignedchar>(_buffer[_position])>' '){++_position;}value.append(_buffer+begin,_position-begin);if(_position<_length){++_position;returntrue;}if(!refill())returntrue;}}boolread(bool&value){intx;if(!read(x))returnfalse;value=x!=0;returntrue;}template<classT>std::enable_if_t<internal::is_integral_v<T>&&!std::is_same_v<std::remove_cv_t<T>,bool>&&!std::is_same_v<std::remove_cv_t<T>,char>,bool>read(T&value){if(_streaming)returnread_integer_from_stream(value);if(!prepare_number())returnfalse;intc=static_cast<unsignedchar>(_buffer[_position++]);while(c<=' ')c=static_cast<unsignedchar>(_buffer[_position++]);boolnegative=false;if(c=='-'){negative=true;c=static_cast<unsignedchar>(_buffer[_position++]);}ifconstexpr(internal::is_signed_v<T>){Tresult=0;while('0'<=c&&c<='9'){constintfirst=c-'0';constintsecond=static_cast<unsignedchar>(_buffer[_position])-'0';if(0<=second&&second<=9){result=negative?result*100-(first*10+second):result*100+(first*10+second);++_position;}else{result=negative?result*10-first:result*10+first;}c=static_cast<unsignedchar>(_buffer[_position++]);}value=result;}else{Tresult=0;while('0'<=c&&c<='9'){constunsignedfirst=unsigned(c-'0');constintsecond=static_cast<unsignedchar>(_buffer[_position])-'0';if(0<=second&&second<=9){result=result*100+T(first*10+unsigned(second));++_position;}else{result=result*10+T(first);}c=static_cast<unsignedchar>(_buffer[_position++]);}value=negative?T(0)-result:result;}if(_position>_length)_position=_length;returntrue;}template<classT>std::enable_if_t<std::is_floating_point_v<T>,bool>read(T&value){if(!skip_spaces())returnfalse;intc=read_char_raw();boolnegative=false;if(c=='-'||c=='+'){negative=c=='-';c=read_char_raw();}longdoubleresult=0;while('0'<=c&&c<='9'){result=result*10+(c-'0');c=read_char_raw();}if(c=='.'){longdoubleplace=0.1L;c=read_char_raw();while('0'<=c&&c<='9'){result+=(c-'0')*place;place*=0.1L;c=read_char_raw();}}if(c=='e'||c=='E'){c=read_char_raw();boolexponent_negative=false;if(c=='-'||c=='+'){exponent_negative=c=='-';c=read_char_raw();}intexponent=0;while('0'<=c&&c<='9'){exponent=exponent*10+(c-'0');c=read_char_raw();}longdoublescale=1;longdoublepower=10;while(exponent>0){if(exponent&1)scale*=power;power*=power;exponent>>=1;}result=exponent_negative?result/scale:result*scale;}value=static_cast<T>(negative?-result:result);returntrue;}template<classT>std::enable_if_t<internal::has_val_method_v<T>&&!internal::is_integral_v<T>&&!internal::is_range_v<T>,bool>read(T&value){longlongx;if(!read(x))returnfalse;ifconstexpr(internal::has_static_mod_raw_v<T>){if(x>=0&&uint64_t(x)<uint64_t(T::mod())){value=T::raw(uint32_t(x));}else{value=T(x);}}else{value=T(x);}returntrue;}template<classFirst,classSecond>boolread(std::pair<First,Second>&value){if(!read(value.first))returnfalse;returnread(value.second);}template<classRange>std::enable_if_t<internal::is_range_v<Range>&&!internal::is_string_like_v<Range>,bool>read(Range&range){usingStoredValue=internal::range_stored_value_t<Range>;constexprboolnested=internal::is_range_v<StoredValue>&&!internal::is_string_like_v<StoredValue>;for(auto&&value:range){ifconstexpr(std::is_same_v<StoredValue,bool>&&!nested){boolx;if(!read(x))returnfalse;value=x;}else{if(!read(value))returnfalse;}}returntrue;}template<classFirst,classSecond,class...Rest>boolread(First&first,Second&second,Rest&...rest){if(!read(first))returnfalse;returnread(second,rest...);}template<classT>FastInput&operator>>(T&value){if(!read(value))std::abort();return*this;}};structFastOutput{staticconstexprintbuffer_size=1<<20;private:inlinestaticconstautodigit_quads=[]{std::array<char,40000>result{};for(inti=0;i<10000;i++){intvalue=i;for(intj=3;j>=0;j--){result[4*i+j]=char('0'+value%10);value/=10;}}returnresult;}();std::FILE*_stream;char_buffer[buffer_size];int_position;int_precision;std::chars_format_float_format;char_range_separator;std::string*_capture=nullptr;template<classT>std::stringformat_cell(constT&value){std::stringresult;structCaptureGuard{std::string*⌖std::string*previous;~CaptureGuard(){target=previous;}}guard{_capture,_capture};_capture=&result;write(value);returnresult;}template<classMatrix>voidwrite_aligned_matrix(constMatrix&matrix){std::vector<std::vector<std::string>>rows;std::vector<std::size_t>widths;for(constauto&row:matrix){auto&cells=rows.emplace_back();std::size_tcolumn=0;for(constauto&value:row){cells.push_back(format_cell(value));if(column==widths.size())widths.push_back(0);widths[column]=std::max(widths[column],cells.back().size());++column;}}boolfirst=true;for(constauto&row:rows){if(!first)write_char('\n');first=false;for(std::size_tcolumn=0;column<row.size();++column){if(column!=0)write_char(_range_separator);for(std::size_tpadding=row[column].size();padding<widths[column];++padding){write_char(' ');}write(row[column]);}}}public:explicitFastOutput(std::FILE*stream=stdout):_stream(stream),_position(0),_precision(6),_float_format(std::chars_format::general),_range_separator(' '){if(_stream==stdout&&internal::standard_output_instance==nullptr){internal::standard_output_instance=this;}}FastOutput(constFastOutput&)=delete;FastOutput&operator=(constFastOutput&)=delete;~FastOutput(){flush();if(internal::standard_output_instance==this){internal::standard_output_instance=nullptr;}}voidflush(){if(_position!=0){std::fwrite(_buffer,1,_position,_stream);_position=0;}std::fflush(_stream);}voidwrite_char(charc){if(_capture!=nullptr){_capture->push_back(c);return;}if(_position==buffer_size)flush();_buffer[_position++]=c;}voidwrite(constchar*s){while(*s!='\0')write_char(*s++);}voidwrite(conststd::string&s){if(_capture!=nullptr){_capture->append(s);return;}std::size_tposition=0;while(position<s.size()){if(_position==buffer_size)flush();conststd::size_tcopied=std::min<std::size_t>(buffer_size-_position,s.size()-position);std::memcpy(_buffer+_position,s.data()+position,copied);_position+=int(copied);position+=copied;}}voidwrite(charc){write_char(c);}voidwrite(boolvalue){write_char(value?'1':'0');}template<classT>std::enable_if_t<std::is_floating_point_v<T>>write(Tvalue){chardigits[128];auto[end,error]=std::to_chars(digits,digits+sizeof(digits),value,_float_format,_precision);if(error!=std::errc())std::abort();for(constchar*pointer=digits;pointer!=end;pointer++){write_char(*pointer);}}template<classT>std::enable_if_t<internal::is_integral_v<T>&&!std::is_same_v<std::remove_cv_t<T>,bool>&&!std::is_same_v<std::remove_cv_t<T>,char>>write(Tvalue){usingRaw=std::remove_cv_t<T>;usingUnsigned=internal::make_unsigned_t<Raw>;Unsignedmagnitude;ifconstexpr(internal::is_signed_v<Raw>){if(value<0){write_char('-');magnitude=Unsigned(0)-Unsigned(value);}else{magnitude=Unsigned(value);}}else{magnitude=value;}if(magnitude==0){write_char('0');return;}unsignedchunks[16];intcount=0;while(magnitude>=10000){constUnsignedquotient=magnitude/10000;chunks[count++]=unsigned(magnitude-quotient*10000);magnitude=quotient;}if(_capture==nullptr&&_position>buffer_size-64)flush();charcaptured[64];char*constbegin=_capture!=nullptr?captured:_buffer+_position;char*destination=begin;constunsignedleading=unsigned(magnitude);constchar*first=digit_quads.data()+4*leading;intskip=leading<10?3:leading<100?2:leading<1000?1:0;for(;skip<4;skip++)*destination++=first[skip];while(count--){constchar*digits=digit_quads.data()+4*chunks[count];std::memcpy(destination,digits,4);destination+=4;}if(_capture!=nullptr){_capture->append(begin,destination-begin);}else{_position+=int(destination-begin);}}template<classT>std::enable_if_t<internal::has_val_method_v<T>&&!internal::is_integral_v<T>&&!internal::is_range_v<T>>write(constT&value){write(value.val());}template<classFirst,classSecond>voidwrite(conststd::pair<First,Second>&value){write(value.first);write_char(' ');write(value.second);}template<classRange>std::enable_if_t<internal::is_range_v<Range>&&!internal::is_string_like_v<Range>>write(constRange&range){usingStoredValue=internal::range_stored_value_t<constRange>;constexprboolnested=internal::is_range_v<StoredValue>&&!internal::is_string_like_v<StoredValue>;boolfirst=true;for(constauto&value:range){if(!first)write_char(nested?'\n':_range_separator);first=false;ifconstexpr(std::is_same_v<StoredValue,bool>&&!nested){write(static_cast<bool>(value));}else{write(value);}}}template<classFirst,class...Rest>voidprint(constFirst&first,constRest&...rest){write(first);((write_char(' '),write(rest)),...);}voidprintln(){write_char('\n');}voidset_precision(intprecision){_precision=precision;}voidset_fixed(intprecision=6){_float_format=std::chars_format::fixed;_precision=precision;}voidset_general(intprecision=6){_float_format=std::chars_format::general;_precision=precision;}voidset_range_separator(charseparator){_range_separator=separator;}template<classMatrix>voidwrite_aligned(constMatrix&matrix){usingRow=internal::range_stored_value_t<constMatrix>;usingCell=internal::range_stored_value_t<constRow>;static_assert(internal::is_range_v<Row>&&!internal::is_string_like_v<Row>,"write_aligned requires a two-dimensional range");static_assert(!internal::is_range_v<Cell>||internal::is_string_like_v<Cell>,"write_aligned requires scalar cells");write_aligned_matrix(matrix);}template<classMatrix>voidprintln_aligned(constMatrix&matrix){write_aligned(matrix);write_char('\n');}template<class...Args>voidprintln(constArgs&...args){print(args...);write_char('\n');}template<classT>FastOutput&operator<<(constT&value){write(value);return*this;}};}// namespace utilities}// namespace m1une#line 12 "verify/string/string_algorithms.test.cpp"
namespace{voidtest_edge_cases(){std::stringempty;assert(m1une::string::z_algorithm(empty).empty());assert(m1une::string::prefix_function(empty).empty());assert(m1une::string::suffix_array(empty).empty());assert(m1une::string::lcp_array(empty,std::vector<int>()).empty());assert(m1une::string::lyndon_factor_boundaries(empty)==std::vector<int>(1,0));assert(m1une::string::lyndon_factorization(empty).empty());assert(m1une::string::minimum_cyclic_shift(empty)==0);autoempty_palindromes=m1une::string::manacher(empty);assert(empty_palindromes.empty());assert(empty_palindromes.longest_length()==0);assert(empty_palindromes.is_palindrome(0,0));std::stringtext="aaaa";assert(m1une::string::kmp_search(text,std::string("aa"))==std::vector<int>({0,1,2}));assert(m1une::string::kmp_search(text,empty)==std::vector<int>({0,1,2,3,4}));std::vector<int>values;values.push_back(2);values.push_back(-1);values.push_back(2);assert(m1une::string::suffix_array(values)==std::vector<int>({1,2,0}));assert(m1une::string::z_algorithm(values)==std::vector<int>({3,0,1}));assert(m1une::string::lyndon_factor_boundaries(values)==std::vector<int>({0,1,3}));assert(m1une::string::minimum_cyclic_shift(values)==1);std::stringbytes;bytes.push_back(char(255));bytes.push_back(char(0));bytes.push_back(char(128));assert(m1une::string::suffix_array(bytes)==std::vector<int>({1,2,0}));}voidtest_randomized(){std::uint64_tstate=31;autorandom=[&state](){state^=state<<7;state^=state>>9;returnstate;};for(inttrial=0;trial<1500;trial++){intn=int(random()%45);std::stringtext(n,'a');for(char&character:text)character=char('a'+random()%4);std::vector<int>z=m1une::string::z_algorithm(text);for(inti=0;i<n;i++){[[maybe_unused]]intexpected=0;while(i+expected<n&&text[expected]==text[i+expected]){expected++;}assert(z[i]==expected);}std::vector<int>prefix=m1une::string::prefix_function(text);for(inti=0;i<n;i++){[[maybe_unused]]intexpected=0;for(intlength=1;length<=i;length++){if(text.substr(0,length)==text.substr(i-length+1,length)){expected=length;}}assert(prefix[i]==expected);}intpattern_length=int(random()%12);std::stringpattern(pattern_length,'a');for(char&character:pattern)character=char('a'+random()%4);std::vector<int>expected_occurrences;for(inti=0;i+pattern_length<=n;i++){if(text.substr(i,pattern_length)==pattern){expected_occurrences.push_back(i);}}assert(m1une::string::kmp_search(text,pattern)==expected_occurrences);m1une::string::ManacherResultpalindromes=m1une::string::manacher(text);intlongest=0;for(intleft=0;left<=n;left++){for(intright=left;right<=n;right++){boolexpected=true;for(intoffset=0;offset<(right-left)/2;offset++){if(text[left+offset]!=text[right-1-offset]){expected=false;break;}}assert(palindromes.is_palindrome(left,right)==expected);if(expected)longest=std::max(longest,right-left);}}assert(palindromes.longest_length()==longest);std::vector<int>suffixes=m1une::string::suffix_array(text);std::vector<int>expected_suffixes(n);std::iota(expected_suffixes.begin(),expected_suffixes.end(),0);std::sort(expected_suffixes.begin(),expected_suffixes.end(),[&text](inta,intb){returntext.substr(a)<text.substr(b);});assert(suffixes==expected_suffixes);std::vector<int>lcp=m1une::string::lcp_array(text,suffixes);for(inti=0;i+1<n;i++){intexpected=0;while(suffixes[i]+expected<n&&suffixes[i+1]+expected<n&&text[suffixes[i]+expected]==text[suffixes[i+1]+expected]){expected++;}assert(lcp[i]==expected);}std::vector<std::pair<int,int>>lyndon_factors=m1une::string::lyndon_factorization(text);intminimum_shift=m1une::string::minimum_cyclic_shift(text);assert((n==0&&minimum_shift==0)||(0<=minimum_shift&&minimum_shift<n));std::stringrestored;std::vector<std::string>factor_words;for(auto[left,right]:lyndon_factors){assert(0<=left&&left<right&&right<=n);std::stringword=text.substr(left,right-left);restored+=word;factor_words.push_back(word);}assert(restored==text);for(inti=0;i+1<int(factor_words.size());i++){assert(!(factor_words[i]<factor_words[i+1]));}}}}// namespaceintmain(){m1une::utilities::FastInputfast_input;m1une::utilities::FastOutputfast_output;test_edge_cases();test_randomized();longlonga,b;fast_input>>a>>b;fast_output<<a+b<<'\n';}