【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 }
原文地址:https://www.cnblogs.com/dcdcbigbig/p/10135665.html