Meow named on the planet
Given a set of strings S, each S given T ask how many strings contained in T, each of the last query S contains a string of how many times a given T.
Thinking
Consider these strings to establish broad S SAM, then every time we would go SAM T into broad match, the last match to the child's parent tree nodes in the number of end position different from the first string is asked the answer.
Similarly, we finished every match after marking at the node, the answer to the second question in each string S is the end of each location have been able to jump up marking the different nodes of the chain and jump.
Consider how the above process, in the generalized SAM, it is assumed the number of active nodes a node in the SAM is \ (S_i \) , it can be shown that \ (\ sum_ {i = 1 } ^ {n} S_i \ leq n \ sqrt 2n} {\) , so we only need to first ask to violence statistics parent tree node to an ending position for each marker violent parent tree nodes, asking each second end position.
/*=======================================
* Author : ylsoi
* Time : 2019.7.2
* Problem : luogu2336
* E-mail : [email protected]
* ====================================*/
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
#define debug(x) cout<<#x<<"="<<x<<" "
#define fi first
#define se second
#define mk make_pair
#define pb push_back
typedef long long ll;
using namespace std;
void File(){
freopen("luogu2336.in","r",stdin);
freopen("luogu2336.out","w",stdout);
}
template<typename T>void read(T &_){
_=0; T f=1; char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())_=(_<<1)+(_<<3)+(c^'0');
_*=f;
}
string proc(){
ifstream f("/proc/self/status");
return string(istreambuf_iterator<char>(f),istreambuf_iterator<char>());
}
const int maxn=2e5+10;
int n,m,name[maxn],len1[maxn],len2[maxn];
unordered_map<int,int>ch[maxn<<1];
int fa[maxn<<1],len[maxn<<1],cnt=1,last=1;
int vis[maxn<<1],sz[maxn<<1],fg[maxn<<1];
void insert(int x){
int p=last,np=last=++cnt;
len[np]=len[p]+1;
while(p && !ch[p][x])ch[p][x]=np,p=fa[p];
if(!p)fa[np]=1;
else{
int q=ch[p][x];
if(len[q]==len[p]+1)fa[np]=q;
else{
int nq=++cnt;
ch[nq]=ch[q],len[nq]=len[p]+1,fa[nq]=fa[q];
fa[q]=fa[np]=nq;
while(p && ch[p][x]==q)ch[p][x]=nq,p=fa[p];
}
}
}
void update(int p,int id){
for(;p && vis[p]!=id;p=fa[p])
vis[p]=id,++sz[p];
}
int query(int p,int id){
int ret=0;
for(;p && vis[p]!=id;p=fa[p])
vis[p]=id,ret+=fg[p];
return ret;
}
int main(){
File();
read(n),read(m);
int now=0;
REP(i,1,n){
read(len1[i]),last=1;
REP(j,1,len1[i])read(name[++now]),insert(name[now]);
read(len2[i]),last=1;
REP(j,1,len2[i])read(name[++now]),insert(name[now]);
}
now=0;
REP(i,1,n){
int o=1;
REP(j,1,len1[i])update(o=ch[o][name[++now]],i);
o=1;
REP(j,1,len2[i])update(o=ch[o][name[++now]],i);
}
REP(i,1,m){
int len0,x,o=1;
read(len0);
REP(j,1,len0)read(x),o=ch[o][x];
printf("%d\n",sz[o]);
++fg[o];
}
memset(vis,0,sizeof(vis));
now=0;
REP(i,1,n){
int o=1,ans=0;
REP(j,1,len1[i])ans+=query(o=ch[o][name[++now]],i);
o=1;
REP(j,1,len2[i])ans+=query(o=ch[o][name[++now]],i);
printf("%d ",ans);
}
return 0;
}