【XSY2384】【GDOI2017】微信
致去年的我:这是道广义SAM模板题啊……
题意:
Description
Input
Output
HINT
$1\leq N\leq 20$,$1\leq Q\leq 10^5$,字符串总长$\leq 10^6$
题解:
题意就是求若干个trie的最长公共子串……
先把所有trie并起来建广义SAM,记录一下每个节点原来属于哪个trie,由于$N$很小,可以直接状压DP,按照parent树从上往下转移就好了……
预处理答案,询问可以$O(1)$处理;
但是本题有一个坑点是广义SAM必须要bfs建立以达到严格$O(n\times 字符集大小)$的时间复杂度,否则会被特殊构造的数据卡到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\n",f[t]);
94 }
95 return 0;
96 }