【XSY2384】【GDOI2017】微信

致去年的我:這是道廣義SAM模板題啊……ios

題意:

Description

Input

Output

HINT

$1\leq N\leq 20$,$1\leq Q\leq 10^5$,字符串總長$\leq 10^6$ui

題解:

題意就是求若干個trie的最長公共子串……spa

先把全部trie並起來建廣義SAM,記錄一下每一個節點原來屬於哪一個trie,因爲$N$很小,能夠直接狀壓DP,按照parent樹從上往下轉移就行了……code

預處理答案,詢問能夠$O(1)$處理;blog

可是本題有一個坑點是廣義SAM必需要bfs創建以達到嚴格$O(n\times 字符集大小)$的時間複雜度,不然會被特殊構造的數據卡到85分。ip

代碼:

 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 }
相關文章
相關標籤/搜索