zoukankan      html  css  js  c++  java
  • bzoj3879 SvT

    Description

    (我并不想告诉你题目名字是什么鬼)

    有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n].

    现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始位置来表示),求这些后缀两两之间的LCP(LongestCommonPrefix)的长度之和.一对后缀之间的LCP长度仅统计一遍.

    Input

    第一行两个正整数n,m,分别表示S的长度以及询问的次数.

    接下来一行有一个字符串S.

    接下来有m组询问,对于每一组询问,均按照以下格式在一行内给出:

    首先是一个整数t,表示共有多少个后缀.接下来t个整数分别表示t个后缀在字符串S中的出现位置.

    Output

    对于每一组询问,输出一行一个整数,表示该组询问的答案.由于答案可能很大,仅需要输出这个答案对于23333333333333333(一个巨大的质数)取模的余数.

    Sample Input

    7 3
    popoqqq
    1 4
    2 3 5
    4 1 2 5 6

    Sample Output

    0
    0
    2
    Hint
    样例解释:
    对于询问一,只有一个后缀”oqqq”,因此答案为0.
    对于询问二,有两个后缀”poqqq”以及”qqq”,两个后缀之间的LCP为0,因此答案为0.
    对于询问三,有四个后缀”popoqqq”,”opoqqq”,”qqq”,”qq”,其中只有”qqq”,”qq”两个后缀之间的LCP不为0,且长度为2,因此答案为2.
    对于100%的测试数据,有S<=5*10^5,且Σt<=3*10^6.
    特别注意:由于另一世界线的某些参数发生了变化,对于一组询问,即使一个后缀出现了多次,也仅算一次.
     
    正解:后缀自动机+后缀树+虚树。
    还是一样的套路。反串后缀自动机构出后缀树,然后我们每次可以建一棵虚树来搞树形$dp$。
     
     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 #define M (6000010)
     6 #define N (1000010)
     7 
     8 using namespace std;
     9 
    10 struct edge{ int nt,to; }g[N<<1];
    11 
    12 int head[N],top[N],fa[N],son[N],Sz[N],dep[N],dfn[N],ed[N],val[N],vis[N],a[M],st[M],n,m,num,cnt;
    13 int ch[N][26],l[N],sz[N],pos[N],la,tot,len;
    14 char s[N];
    15 ll ans;
    16 
    17 il int gi(){
    18   RG int x=0,q=1; RG char ch=getchar();
    19   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    20   if (ch=='-') q=-1,ch=getchar();
    21   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    22   return q*x;
    23 }
    24 
    25 il void add(RG int c){
    26   RG int p=la,np=++tot; la=np,l[np]=l[p]+1,sz[np]=1;
    27   for (;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
    28   if (!p){ fa[np]=1; return; } RG int q=ch[p][c];
    29   if (l[q]==l[p]+1) fa[np]=q; else{
    30     RG int nq=++tot; l[nq]=l[p]+1;
    31     fa[nq]=fa[q],fa[q]=fa[np]=nq;
    32     memcpy(ch[nq],ch[q],sizeof(ch[q]));
    33     for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
    34   }
    35   return;
    36 }
    37 
    38 il void insert(RG int from,RG int to){
    39   g[++num]=(edge){head[from],to},head[from]=num; return;
    40 }
    41 
    42 il void dfs1(RG int x){
    43   dep[x]=dep[fa[x]]+1,Sz[x]=1; RG int v;
    44   for (RG int i=head[x];i;i=g[i].nt){
    45     v=g[i].to,dfs1(v),Sz[x]+=Sz[v];
    46     if (Sz[son[x]]<=Sz[v]) son[x]=v;
    47   }
    48   return;
    49 }
    50 
    51 il void dfs2(RG int x,RG int anc){
    52   top[x]=anc,dfn[x]=++cnt;
    53   if (son[x]) dfs2(son[x],anc);
    54   for (RG int i=head[x];i;i=g[i].nt)
    55     if (g[i].to!=son[x]) dfs2(g[i].to,g[i].to);
    56   ed[x]=cnt; return;
    57 }
    58 
    59 il void dfs(RG int x){
    60   val[x]=vis[x]*sz[x];
    61   for (RG int i=head[x],v;i;i=g[i].nt){
    62     v=g[i].to,dfs(v);
    63     ans+=1LL*l[x]*val[x]*val[v],val[x]+=val[v];
    64   }
    65   return;
    66 }
    67 
    68 il int lca(RG int u,RG int v){
    69   while (top[u]!=top[v]){
    70     if (dep[top[u]]<dep[top[v]]) swap(u,v);
    71     u=fa[top[u]];
    72   }
    73   return dep[u]<dep[v] ? u : v;
    74 }
    75 
    76 il int cmp(const int &a,const int &b){ return dfn[a]<dfn[b]; }
    77 
    78 int main(){
    79 #ifndef ONLINE_JUDGE
    80   freopen("svt.in","r",stdin);
    81   freopen("svt.out","w",stdout);
    82 #endif
    83   n=gi(),m=gi(),la=++tot,scanf("%s",s+1);
    84   for (RG int i=n;i;--i) add(s[i]-'a'),pos[i]=la;
    85   for (RG int i=2;i<=tot;++i) insert(fa[i],i); dfs1(1),dfs2(1,1);
    86   for (RG int i=1;i<=tot;++i) head[i]=0; num=0;
    87   while (m--){
    88     RG int t=gi(),tt=t; for (RG int i=1;i<=t;++i) a[i]=pos[gi()],vis[a[i]]=1; sort(a+1,a+t+1,cmp);
    89     for (RG int i=2;i<=t;++i) if (ed[a[i-1]]<dfn[a[i]]) a[++tt]=lca(a[i-1],a[i]);
    90     sort(a+1,a+tt+1,cmp),tt=unique(a+1,a+tt+1)-a-1; RG int top=1; st[top]=a[1];
    91     for (RG int i=2;i<=tt;++i){
    92       while (ed[st[top]]<dfn[a[i]]) --top;
    93       insert(st[top],a[i]),st[++top]=a[i];
    94     }
    95     ans=0,dfs(a[1]),printf("%lld
    ",ans),num=0;
    96     for (RG int i=1;i<=tt;++i) head[a[i]]=vis[a[i]]=0;
    97   }
    98   return 0;
    99 }
  • 相关阅读:
    一脚踩进java之基础篇07——数组
    一脚踩进java之基础篇06——流程控制语句(if...else,while,for,switch...case)
    一脚踩进java之基础篇05——运算符
    一脚踩进java之基础篇04——变量
    [转]进程间通信
    [转]netstat 命令详解
    僵尸进程
    如何进行表的复制
    解决system调用返回ECHILD的问题
    Oracle保留2位小数
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7631414.html
Copyright © 2011-2022 走看看