zoukankan      html  css  js  c++  java
  • BZOJ3277: 串(后缀自动机,Parent树,Dfs序)

    Description

    字符串是oi界常考的问题。现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中
    至少k个字符串的子串(注意包括本身)。

    Input

    第一行两个整数n,k。
    接下来n行每行一个字符串。
    n,k,l<=100000

    Output

    输出一行n个整数,第i个整数表示第i个字符串的答案。

    Sample Input

    3 1
    abc
    a
    ab

    Sample Output

    6 1 3

    解题思路:

    k个嘛,好像可以离线树状数组QAQ,具体的像这样,只不过需要将所有节点都询问一遍。

    最后,找子串嘛,短的不多于k个长的肯定也不行,利用这个性质,只要不够k就跳pre,直到大于等于k。

    而以这个节点为后缀的子串共有len个,ans+=len就好了。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 const int N=400000;
      5 struct sant{
      6     int tranc[26];
      7     int len;
      8     int pre;
      9 }s[N];
     10 struct pnt{
     11     int hd;
     12     int ind;
     13     int oud;
     14     int col;
     15     int ans;
     16 }p[N];
     17 struct ent{
     18     int twd;
     19     int lst;
     20 }e[N];
     21 struct int_2{
     22     int l;
     23     int r;
     24     int no;
     25 }d[N];
     26 int n,k;
     27 int siz;
     28 int dfn;
     29 int cnt;
     30 int fin;
     31 char tmp[N];
     32 int ll[N],rr[N];
     33 int col[N];
     34 int lst[N];
     35 int line[N];
     36 int str[N];
     37 int lowbit(int x)
     38 {
     39     return x&(-x);
     40 }
     41 void update(int pos,int x)
     42 {
     43     while(pos&&pos<=dfn)
     44     {
     45         line[pos]+=x;
     46         pos+=lowbit(pos);
     47     }
     48     return ;
     49 }
     50 int query(int pos)
     51 {
     52     int ans=0;
     53     while(pos)
     54     {
     55         ans+=line[pos];
     56         pos-=lowbit(pos);
     57     }
     58     return ans;
     59 }
     60 bool cmp(int_2 x,int_2 y)
     61 {
     62     return x.r<y.r;
     63 }
     64 void ade(int f,int t)
     65 {
     66     cnt++;
     67     e[cnt].twd=t;
     68     e[cnt].lst=p[f].hd;
     69     p[f].hd=cnt;
     70     return ;
     71 }
     72 void Insert(int c,int pl)
     73 {
     74     int nwp,nwq,lsp,lsq;
     75     nwp=++siz;
     76     s[nwp].len=s[fin].len+1;
     77     p[nwp].col=pl;
     78     for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)
     79         s[lsp].tranc[c]=nwp;
     80     if(!lsp)
     81         s[nwp].pre=1;
     82     else{
     83         lsq=s[lsp].tranc[c];
     84         if(s[lsq].len==s[lsp].len+1)
     85             s[nwp].pre=lsq;
     86         else{
     87             nwq=++siz;
     88             s[nwq]=s[lsq];
     89             s[nwq].len=s[lsp].len+1;
     90             s[lsq].pre=s[nwp].pre=nwq;
     91             while(s[lsp].tranc[c]==lsq)
     92             {
     93                 s[lsp].tranc[c]=nwq;
     94                 lsp=s[lsp].pre;
     95             }
     96         }
     97     }
     98     fin=nwp;
     99 }
    100 void Dfs(int x)
    101 {
    102     p[x].ind=++dfn;
    103     col[dfn]=p[x].col;
    104     for(int i=p[x].hd;i;i=e[i].lst)
    105     {
    106         int to=e[i].twd;
    107         Dfs(to);
    108     }
    109     p[x].oud=++dfn;
    110     col[dfn]=p[x].col;
    111 }
    112 int main()
    113 {
    114     scanf("%d%d",&n,&k);
    115     if(k>n)
    116     {
    117         for(int i=1;i<=n;i++)
    118             printf("%d ",0);
    119         return 0;
    120     }
    121     fin=++siz;
    122     for(int i=1;i<=n;i++)
    123     {
    124         ll[i]=rr[i-1]+1;
    125         rr[i]=rr[i-1];
    126         fin=1;
    127         scanf("%s",tmp);
    128         int len=strlen(tmp);
    129         for(int j=0;j<len;j++)
    130             str[++rr[i]]=tmp[j]-'a';
    131         for(int j=ll[i];j<=rr[i];j++)
    132         {
    133             Insert(str[j],i);
    134         }
    135     }
    136 
    137     for(int i=2;i<=siz;i++)
    138         ade(s[i].pre,i);
    139     Dfs(1);    
    140     for(int i=1;i<=siz;i++)
    141         d[i]=(int_2){p[i].ind,p[i].oud,i};
    142     std::sort(d+1,d+siz+1,cmp);
    143     int r=1;
    144     for(int i=1;i<=siz;i++)
    145     {
    146         while(r<=d[i].r)
    147         {
    148             if(!col[r])
    149             {
    150                 r++;
    151                 continue;
    152             }
    153             if(lst[col[r]])
    154                 update(lst[col[r]],-1);
    155             update(r,1);
    156             lst[col[r]]=r;
    157             r++;
    158         }
    159         r--;
    160         p[d[i].no].ans=query(d[i].r)-query(d[i].l-1);
    161     }
    162     for(int i=1;i<=n;i++)
    163     {
    164         int ans=0;
    165         int root=1;
    166         for(int j=ll[i];j<=rr[i];j++)
    167         {
    168             root=s[root].tranc[str[j]];
    169             while(p[root].ans<k)
    170                 root=s[root].pre;
    171             ans+=s[root].len;
    172         }
    173         printf("%d ",ans);
    174     }
    175     puts("");
    176     return 0;
    177 }
  • 相关阅读:
    图片移动特效
    风云舞
    弹出页面
    javascript放大镜原版
    jquery UI入门
    AJAX demo——操作文本文件
    上一页 1 2 ...10 下一页 百度 GOOGLE 分页
    在后台调用JavaScript打开新页面
    Ext简介
    My97DatePicker
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10046167.html
Copyright © 2011-2022 走看看