• 【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
  • 相关阅读:
    Python合集之Python循环语句(二)
    io流2
    io流
    集合工具类
    泛型
    Map
    VSCode_Extensions
    C++ in VSCode
    C# 私有字段前缀 _ 的设置(VS2019, .editorconfig)
    dotnet 跨平台编译发布
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9892133.html
Copyright © 2020-2023  润新知