SP8093
前言
是通过另一道题来的,觉得这道题是神题就发题解了。
思路
这里我用的 SA 和莫队,我们首先可以得到一个很显然的性质,那就是对于两个串如果互相 \(A\) 在 \(B\) 中出现过那么 \(lcp(A,B)=\min(|A|,|B|)\) 然后我们就可以将所有的模式串拼在一起做一遍 SA。
然后我们继续观察就能发现对于一个查询串,包含它的后缀一定是连续的一串,所以我们可以对于一个查询串在 \(rk\) 数组上求出是哪个区间(这里可以将左右端点分开求,可以二分出小于查询串中的最后一个作为 \(l\) 然后二分出小于等于查询串的最后一个作为 \(r\))。
那么我们就将问题转换为了:给你一个序列,再给你 \(m\) 次询问给你 \(l\) 和 \(r\) 让你求出 \(l\sim r\) 中不同元素的数量。
这不是一眼莫队或者树状数组吗?其实有原题HH的项链。
这里由于我不会 SA 所以用的二分和哈希,要比标算多一个 \(\log\)。
代码
代码又臭又长
#include <bits/stdc++.h>
using namespace std ;
#define int long long
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define rep1(i,x,y) for(int i=x;i>=y;i--)
#define fire signed
#define kong putchar(' ')
#define end putchar('\n')
#define in(x) scanf("%lld",&x)
#define lcm(x,y) x*y/__gcd(x,y)
#define il inline
il void print(int x) {
if(x>=10) print(x/10);
putchar(x%10+'0');
}
int n;
string s,t;
const int N=6e6+10,mod=998244353;
int f[N],jc[N];
int sa[N],l,m;
int get(int u,int r) {
return (f[r]-f[u-1]*jc[r-u+1]%mod+mod)%mod;
}
bool cmp(int x,int y) {
int L=0,r=min(l-x+1,l-y+1),res=0;
while(L<=r) {
int mid=L+r>>1;
if(get(x,x+mid-1)==get(y,y+mid-1)) L=mid+1,res=mid;
else r=mid-1;
}
return s[x+res]<s[y+res];
}
int len;
struct node{
int l,r,id;
friend bool operator<(const node&a,const node&b) {
return a.l/len!=b.l/len?a.l<b.l:a.r<b.r;
}
}q[N];
int cnt[N],id[N],ans,res[N],idx;
void pl(int x) {
cnt[id[sa[x]]]++;
if(cnt[id[sa[x]]]==1) ans++;
}
void jian(int x) {
cnt[id[sa[x]]]--;
if(cnt[id[sa[x]]]==false) ans--;
}
fire main() {
in(n),in(m);
char u='z'+1;
s=" ";
rep(i,1,n) {
cin>>t;
s+=t+'&';
for(auto j:t) id[++l]=i;
l++;
id[l]=i;
}
jc[0]=1;
rep(i,1,l) jc[i]=jc[i-1]*131%mod,f[i]=(f[i-1]*131%mod+s[i]-'a'+1)%mod,sa[i]=i;
stable_sort(sa+1,sa+1+l,cmp);
rep(i,1,m) {
cin>>t;
int lt=t.size();
t=" "+t;
int resl=1,resr=l;
rep(j,1,lt) {
int l=resl,r=resr,res=resl;
while(l<=r) {
int mid=l+r>>1;
if(s[sa[mid]+j-1]<t[j]) l=mid+1,res=mid;
else r=mid-1;
}
int lo=resl;
resl=res+1;
res=1;
l=lo;
r=resr;
while(l<=r) {
int mid=l+r>>1;
if(s[sa[mid]+j-1]<=t[j]) l=mid+1,res=mid;
else r=mid-1;
}
resr=r;
}
if(resl<=resr) q[++idx]={resl,resr,i};
}
len=sqrt(idx);
sort(q+1,q+1+idx);
int l=1,r=0;
rep(i,1,idx) {
while(l<q[i].l) jian(l++);
while(l>q[i].l) pl(--l);
while(r<q[i].r) pl(++r);
while(r>q[i].r) jian(r--);
res[q[i].id]=ans;
}
rep(i,1,m) print(res[i]),end;
return false;
}

浙公网安备 33010602011771号