OJ题号:
洛谷2922
思路:
字典树,每个结点记录经过该节点的字符串数cnt和以该结点结尾的字符串数量val。
每次询问时累加经过节点的val值和结尾结点的cnt值。
1 #include<cstdio> 2 #include<cctype> 3 #include<cstring> 4 inline int getint() { 5 char ch; 6 while(!isdigit(ch=getchar())); 7 int x=ch^'0'; 8 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 9 return x; 10 } 11 class Trie { 12 private: 13 static const int maxnode=500001; 14 int ch[maxnode][2]; 15 int val[maxnode],cnt[maxnode]; 16 int sz; 17 public: 18 Trie() { 19 sz=0; 20 memset(ch,0,sizeof ch); 21 memset(val,0,sizeof val); 22 memset(cnt,0,sizeof cnt); 23 } 24 void insert(int *s) { 25 int x=0,n=s[0]; 26 for(int i=1;i<=n;i++) { 27 if(!ch[x][s[i]]) { 28 ch[x][s[i]]=++sz; 29 } 30 cnt[x]++; 31 x=ch[x][s[i]]; 32 } 33 val[x]++; 34 } 35 int query(int *s) { 36 int x=0,n=s[0],ans=0; 37 for(int i=1;i<=n;i++) { 38 ans+=val[x]; 39 if(!ch[x][s[i]]) { 40 return ans; 41 } 42 x=ch[x][s[i]]; 43 } 44 return ans+val[x]+cnt[x]; 45 } 46 }; 47 Trie t; 48 int main() { 49 int m=getint(),n=getint(); 50 int s[10001]; 51 while(m--) { 52 s[0]=getint(); 53 for(int i=1;i<=s[0];i++) s[i]=getint(); 54 t.insert(s); 55 } 56 while(n--) { 57 s[0]=getint(); 58 for(int i=1;i<=s[0];i++) s[i]=getint(); 59 printf("%d ",t.query(s)); 60 } 61 return 0; 62 }