做点字符串题

547E. Mike and Friends
题意:
给定(n)个字符串(s_1,cdots,s_n),定义(f(i,j))(s_i)(s_j)作为子串出现次数.
给出(q)个询问((l,r,k)),求(displaystylesum_{i=l}^rf(i,k).)
首先只需要求(f(i,k))关于(i)的前缀和进行作差.然后考虑对(i)按顺序加入贡献,每次对(k)进行询问.
第一种做法是使用AC自动机,如果(s_k)(s_{i1}cdots s_{im})的后缀,那么在fail树上(s_{i1}cdots s_{im})对应节点是(s_j)对应节点的后代.
因此需要使用DFS序进行单点增加(1)和子树和询问.
第二种做法是使用后缀数组,如果(s_k)(s_{im}cdots s_{i|s_i|})的前缀,那么在height数组中两者排名对应位置间所有数都大于或等于(|s_k|).
使用单调栈和二分可以求出每个(s_k)在后缀数组中与它LCP大于或等于(|s_k|)的范围,然后同样使用单点修改和区间求和统计答案.
如果记(m=sum_{i=1}^n|s|),两种做法复杂度都是时间(O(m+qlog m)),空间(O(m+q)).

204E. Little Elephant and Strings
题意:
给定(n)个字符串(s_1,cdots,s_n)和整数(k),对每个字符串求有多少个子串存在至少(k)个字符串包含这个子串.
显然如果(s_i[l,r])是答案,那么([l,r])的所有子区间([x,y])也是答案.因此可以使用双指针.
想要验证(s_i[l,r])是答案,可以通过使用height数组二分在后缀数组上找到对应的区间,转换为区间求颜色数问题.
由于只需要验证颜色数是否至少为(k),可以再次使用双指针来队每个区间左端点求出颜色至少为(k)的右端点中的最小值.
时间和空间复杂度都是(O(mlog m)).

原文地址:https://www.cnblogs.com/Heltion/p/13955848.html