zoukankan      html  css  js  c++  java
  • 【XSY2384】【GDOI2017】微信

    致去年的我:这是道广义SAM模板题啊……

    题意:

    Description

    Input

    Output

    HINT

    $1leq Nleq 20$,$1leq Qleq 10^5$,字符串总长$leq 10^6$

    题解:

    题意就是求若干个trie的最长公共子串……

    先把所有trie并起来建广义SAM,记录一下每个节点原来属于哪个trie,由于$N$很小,可以直接状压DP,按照parent树从上往下转移就好了……

    预处理答案,询问可以$O(1)$处理;

    但是本题有一个坑点是广义SAM必须要bfs建立以达到严格$O(n imes 字符集大小)$的时间复杂度,否则会被特殊构造的数据卡到85分。

    代码:

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<queue>
     7 #define inf 2147483647
     8 #define eps 1e-9
     9 using namespace std;
    10 typedef long long ll;
    11 typedef double db;
    12 int n,qq,t,top,len,last,cnt=1,tot=1,rt=1,rts[1000001],s1[2000001],s2[2000001],son[2000001][26],fa[2000001],mx[2000001],s[2000001],p[2000001],ch[1000001][26],ss[1000001],f[1200001];
    13 char st[1000001],nw[1000001],qr[20];
    14 queue<int>q;
    15 void ins(char *s,int len,int id){
    16     int nw=rts[len-1];
    17     if(!ch[nw][s[len]-'a'])ch[nw][s[len]-'a']=++cnt;
    18     ss[ch[nw][s[len]-'a']]|=id;
    19     rts[len]=ch[nw][s[len]-'a'];
    20 }
    21 int extend(int p,int ch,int id){
    22     int np=++tot;
    23     mx[np]=mx[p]+1;
    24     s[np]=id;
    25     for(;p&&!son[p][ch];p=fa[p])son[p][ch]=np;
    26     if(!p)fa[np]=rt;
    27     else{
    28         int q=son[p][ch];
    29         if(mx[q]==mx[p]+1)fa[np]=q;
    30         else{
    31             int nq=++tot;
    32             s[nq]=id;
    33             mx[nq]=mx[p]+1;
    34             memcpy(son[nq],son[q],sizeof(son[q]));
    35             fa[nq]=fa[q];
    36             fa[q]=fa[np]=nq;
    37             for(;p&&son[p][ch]==q;p=fa[p])son[p][ch]=nq;
    38         }
    39     }
    40     return last=np;
    41 }
    42 void build(){
    43     q.push(rt);
    44     p[rt]=1;
    45     while(!q.empty()){
    46         int u=q.front();
    47         q.pop();
    48         for(int i=0;i<26;i++){
    49             int v=ch[u][i];
    50             if(v){
    51                 p[v]=extend(p[u],i,ss[v]);
    52                 q.push(v);
    53             }
    54         }
    55     }
    56     for(int i=1;i<=tot;i++)s1[mx[i]]++;
    57     for(int i=2;i<=tot;i++)s1[i]+=s1[i-1];
    58     for(int i=1;i<=tot;i++)s2[s1[mx[i]]--]=i;
    59     for(int i=tot;i;i--){
    60         s[fa[s2[i]]]|=s[s2[i]];
    61         f[s[s2[i]]]=max(f[s[s2[i]]],mx[s2[i]]);
    62     }
    63 }
    64 int main(){
    65     scanf("%d",&n);
    66     rts[0]=1;
    67     for(int i=1;i<=n;i++){
    68         scanf("%s",st);
    69         len=strlen(st);
    70         top=0;
    71         for(int j=0;j<len;j++){
    72             if(st[j]=='<')top--;
    73             else{
    74                 nw[++top]=st[j];
    75                 ins(nw,top,1<<(i-1));
    76             }
    77         }
    78     }
    79     build();
    80     for(int i=(1<<n)-1;i>=0;i--){
    81         for(int j=0;j<n;j++){
    82             if((1<<j)&i){
    83                 f[i^(1<<j)]=max(f[i^(1<<j)],f[i]);
    84             }    
    85         }
    86     }
    87     scanf("%d",&qq);
    88     while(qq--){
    89         scanf("%s",qr);
    90         len=strlen(qr);
    91         t=0;
    92         for(int i=len-1;i>=0;i--)t=t*2+qr[i]-'0';
    93         printf("%d
    ",f[t]);
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    Hugo搭建的博客删除文章事宜
    [GIT] Git学习笔记
    VS Code: 解决安装code-runner扩展run后无法在只读编辑器下编辑
    c/c++结构体总结
    恢复U盘做启动盘后的容量
    Manjaro安装Mysql
    win10环境下安装manjaro kde(双系统)
    IDEA设置编辑区主题
    IDEA设置主体、窗体及菜单的字体大小
    IDEA设置项目文件编码
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/10135665.html
Copyright © 2011-2022 走看看