51nod 小Z的trie(Trie+广义SAM)
【题目链接】
http://www.51nod.com/contest/problem.html#!problemId=1647
【题意】
给定一个n个字符串的Trie,每次询问一个字符串在Trie上的出现次数。
【思路】
将n个字符串构造一个Trie,构造广义后缀自动机,识别Trie中的所有子串。
则问题转化为求子串[l,r]在所属字符串中的出现次数,和 这道题 类似,采用树上倍增得到|right|的方法。
比较恶心的是定位字符串的位置=-=。
【代码】
1 #include<set> 2 #include<cmath> 3 #include<queue> 4 #include<vector> 5 #include<cstdio> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt) 10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 11 #define rep(a,b,c) for(int a=(b);a>=(c);a--) 12 using namespace std; 13 14 typedef long long ll; 15 const int N = 1e6+10; 16 const int D = 21; 17 const int maxnode = 1800010; 18 19 int pos[N],pos2[N],cur; 20 21 ll read() { 22 char c=getchar(); 23 ll f=1,x=0; 24 while(!isdigit(c)) { 25 if(c=='-') f=-1; c=getchar(); 26 } 27 while(isdigit(c)) 28 x=x*10+c-'0',c=getchar(); 29 return x*f; 30 } 31 32 struct SAM 33 { 34 int sz,fa[maxnode],mx,ch[maxnode][26],l[maxnode]; 35 int siz[maxnode],b[maxnode],c[N],fat[maxnode][D]; 36 SAM() { 37 sz=1; 38 memset(l,0,sizeof(l)); 39 memset(siz,0,sizeof(siz)); 40 } 41 int add(int c,int p) { 42 int np=++sz; l[np]=l[p]+1; 43 mx=max(mx,l[np]); siz[np]=1; 44 for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np; 45 if(!p) fa[np]=1; 46 else { 47 int q=ch[p][c]; 48 if(l[q]==l[p]+1) fa[np]=q; 49 else { 50 int nq=++sz; l[nq]=l[p]+1; 51 memcpy(ch[nq],ch[q],sizeof(ch[q])); 52 fa[nq]=fa[q]; 53 fa[np]=fa[q]=nq; 54 for(;q==ch[p][c];p=fa[p]) ch[p][c]=nq; 55 } 56 } 57 return np; 58 } 59 void get_pre() { 60 FOR(i,1,sz) c[l[i]]++; 61 FOR(i,1,mx) c[i]+=c[i-1]; 62 FOR(i,1,sz) b[c[l[i]]--]=i; 63 rep(i,sz,1) siz[fa[b[i]]]+=siz[b[i]]; 64 FOR(j,1,sz) { 65 int i=b[j]; //按照拓扑序递推fat 66 fat[i][0]=fa[i]; 67 FOR(j,1,D-1) 68 fat[i][j]=fat[fat[i][j-1]][j-1]; 69 } 70 } 71 int solve(int u,int len) { 72 rep(i,D-1,0) 73 if(l[fat[u][i]]>=len) u=fat[u][i]; 74 return siz[u]; 75 } 76 } sam; 77 78 struct Node { 79 int id,np; 80 }; 81 struct Trie 82 { 83 int sz,ch[N][26]; 84 queue<Node> q; 85 Trie() { 86 sz=0; 87 memset(ch,0,sizeof(ch)); 88 } 89 void insert(char* s) { 90 int u=0; 91 for(int i=0;s[i];i++) { 92 int c=s[i]-'a'; 93 if(!ch[u][c]) ch[u][c]=++sz; 94 u=ch[u][c]; pos[++cur]=u; 95 } 96 } 97 void bfs() { 98 int u=0; 99 q.push((Node){u,1}); 100 while(!q.empty()) { 101 Node qr=q.front(); q.pop(); 102 int u=qr.id,p=qr.np; 103 FOR(c,0,25) if(ch[u][c]) { 104 int v=ch[u][c]; 105 int np=sam.add(c,p); 106 pos2[v]=np; 107 q.push((Node){v,np}); 108 } 109 } 110 } 111 } trie; 112 113 int n,m,len[N]; 114 char s[N]; 115 116 int main() 117 { 118 n=read(); 119 FOR(i,1,n) { 120 scanf("%s",s); 121 len[i]=len[i-1]+strlen(s); 122 trie.insert(s); 123 } 124 trie.bfs(); 125 sam.get_pre(); 126 scanf("%d",&m); 127 int p,x,y; 128 while(m--) { 129 p=read(),x=read(),y=read(); 130 x+=len[p-1],y+=len[p-1]; 131 printf("%d\n",sam.solve(pos2[pos[y]],y-x+1)); 132 } 133 return 0; 134 }
posted on 2016-04-07 11:06 hahalidaxin 阅读(890) 评论(0) 编辑 收藏 举报