• 【BZOJ3227】串【广义后缀自动机】


    题意

      给出n个字符串,问每个字符串中有多少子串是这所有的n个字符串中至少k个的子串。

    分析

      广义后缀自动机模板题。对这n个串建广义后缀自动机,对于每个状态维护两个值cou[u]和lcu[u]分别代表拥有这个状态的子串的数量和上一次更新到这个状态的子串的数量。然后设f[u]为状态u到祖先的所有结点有多少子串出现在至少k个字符串中。然后再跑一边每个子串就可以了。

      

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 
     6 using namespace std;
     7 const int maxn=1e5+100;
     8 typedef long long LL;
     9 string S[maxn];
    10 char s[maxn];
    11 struct state{
    12     int link,len;
    13     int next[26];
    14 }st[2*maxn];
    15 int n,k,last,cur,sz;
    16 int c[2*maxn];
    17 int cou[2*maxn],lcu[2*maxn];//不同子串数量,上一次出现的子串
    18 LL f[maxn];
    19 
    20 void init(){
    21     sz=1;
    22     cur=last=0;
    23     st[0].link=-1;
    24     st[0].len=0;
    25 }
    26 void build_sam(int c){
    27     cur=sz++;
    28     st[cur].len=st[last].len+1;
    29     int p;
    30     for(p=last;p!=-1&&st[p].next[c]==0;p=st[p].link)
    31         st[p].next[c]=cur;
    32     if(p==-1)
    33         st[cur].link=0;
    34     else{
    35         int q=st[p].next[c];
    36         if(st[p].len+1==st[q].len)
    37             st[cur].link=q;
    38         else{
    39             int clone=sz++;
    40             st[clone].len=st[p].len+1;
    41             st[clone].link=st[q].link;
    42             for(int i=0;i<26;i++)
    43                 st[clone].next[i]=st[q].next[i];
    44             for(;p!=-1&&st[p].next[c]==q;p=st[p].link)
    45                 st[p].next[c]=clone;
    46             st[cur].link=st[q].link=clone;
    47         }
    48     }
    49     last=cur;
    50 }
    51 int cmp(int a,int b){
    52     return st[a].len<st[b].len;
    53 }
    54 
    55 int main(){
    56     scanf("%d%d",&n,&k);
    57     init();
    58     for(int i=1;i<=n;i++){
    59         scanf("%s",s);
    60         S[i]=(string)s;
    61         int len=strlen(s);
    62         for(int i=0;i<len;i++)
    63             build_sam(s[i]-'a');
    64         last=0;
    65     }
    66     for(int i=1;i<=n;i++){
    67         int u=0;
    68         for(int j=0;j<S[i].length();j++){
    69             int c=S[i][j]-'a';
    70             u=st[u].next[c];
    71             for(int p=u;p!=-1&&lcu[p]!=i;p=st[p].link)
    72                 lcu[p]=i,cou[p]++;
    73         }
    74     }
    75     for(int i=0;i<sz;i++)
    76         c[i]=i;
    77     sort(c,c+sz,cmp);
    78     for(int i=0;i<sz;i++){
    79         int u=c[i];
    80         if(st[u].link!=-1){
    81             f[u]+=f[st[u].link];
    82             if(cou[u]>=k){
    83                 f[u]+=st[u].len-st[st[u].link].len;
    84             }
    85         }
    86     }
    87     for(int i=1;i<=n;i++){
    88         int u=0;
    89         LL res=0;
    90         for(int j=0;j<S[i].length();j++){
    91             int c=S[i][j]-'a';
    92             u=st[u].next[c];
    93             res+=f[u];
    94         }
    95         printf("%lld
    ",res);
    96     }
    97 
    98 return 0;
    99 }
    View Code
  • 相关阅读:
    单调队列 POJ 2823
    大组合数取mod lucas 定理
    多校4
    多校2
    2016多校1
    百度之星 初赛B续
    iot-web增加apis-namespace组件
    25.75k8s
    新项目增加gradlew
    vue图片点击放大预览v-viewer
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9892133.html
Copyright © 2020-2023  润新知