• 【BZOJ2780】Sevenk Love Oimaster【广义后缀自动机】


    题意

      给出你n个字符串和q个查询,每个查询给出一个字符串s,对于每个查询你都要输出这个字符串s在上面多少个字符串中出现过。

    分析

      广义后缀自动机的裸题。建好SAM以后再跑一遍得到每个状态的ocu和las。然后对于每个查询的字符串,跑到那个状态然后输出那个状态的ocu就可以了。

      

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 
     6 using namespace std;
     7 const int maxn=201000;
     8 struct state{
     9     int len,link,ocu,las;
    10     int next[26];
    11 }st[maxn];
    12 int N,Q,n;
    13 int last,cur,sz;
    14 char s[maxn];
    15 string S[100000+5];
    16 void init(){
    17     sz=1;
    18     cur=last=0;
    19     st[0].link=-1;
    20     st[0].len=0;
    21 }
    22 void build_sam(int c){
    23     cur=sz++;
    24     st[cur].len=st[last].len+1;
    25     int p;
    26     for(p=last;p!=-1&&st[p].next[c]==0;p=st[p].link){
    27             st[p].next[c]=cur;
    28     }
    29     if(p==-1)
    30         st[cur].link=0;
    31     else{
    32         int q=st[p].next[c];
    33         if(st[q].len==st[p].len+1)
    34             st[cur].link=q;
    35         else{
    36             int clone=sz++;
    37             st[clone].len=st[p].len+1;
    38             st[clone].link=st[q].link;
    39             for(int i=0;i<26;i++)
    40                 st[clone].next[i]=st[q].next[i];
    41             for(;p!=-1&&st[p].next[c]==q;p=st[p].link)
    42                 st[p].next[c]=clone;
    43             st[cur].link=st[q].link=clone;
    44         }
    45     }
    46     last=cur;
    47 }
    48 
    49 int main(){
    50     scanf("%d%d",&N,&Q);
    51     init();
    52     for(int i=1;i<=N;i++){
    53         scanf("%s",s);
    54         S[i]=(string)s;
    55         n=strlen(s);
    56         for(int j=0;j<n;j++){
    57             build_sam(s[j]-'a');
    58         }
    59         last=0;
    60     }
    61 
    62     for(int i=1;i<=N;i++){
    63         int u=0;
    64         for(int j=0;j<S[i].length();j++){
    65             u=st[u].next[S[i][j]-'a'];
    66             int p=u;
    67             while(p!=-1&&st[p].las!=i){
    68                 st[p].ocu++;
    69                 st[p].las=i;
    70                 p=st[p].link;
    71             }
    72         }
    73     }
    74 
    75     for(int q=1;q<=Q;q++){
    76         scanf("%s",s);
    77         n=strlen(s);
    78         int u=0,flag=1;
    79         for(int i=0;i<n;i++){
    80             if(st[u].next[s[i]-'a']==0){
    81                 flag=0;
    82                 break;
    83             }
    84             u=st[u].next[s[i]-'a'];
    85         }
    86         if(!flag){
    87             printf("0
    ");
    88         }else
    89         printf("%d
    ",st[u].ocu);
    90     }
    91 
    92 return 0;
    93 }
    View Code
  • 相关阅读:
    C++之容器
    C++之复制控制
    TCP的3次握手/4次握手
    linux编程之多线程编程
    linux编程之信号
    linux编程之共享内存
    MySQL数据库优化
    MySQL存储引擎InnoDB与Myisam
    Redis--持久化
    Redis 请求应答模式和往返延时 Pipelining
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9892199.html
Copyright © 2020-2023  润新知