标签:
给出若干模式串,再给出若干询问串,求每个询问串作为多少个模式串的子串出现。
如果一个串是另一个串的子串,则一定是另一个串某个前缀的后缀或者某个后缀的前缀。根据字典树的性质,将模式串的每一个后缀插入字典树中,同时更新字典树中节点的cnt值。这里需要注意不要重复累加贡献,可以在字典树中新增一个num的信息值来实现这一点。
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <stdio.h> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <set> 11 #include <cmath> 12 #include <ctime> 13 #include <cassert> 14 #include <sstream> 15 using namespace std; 16 17 const int N=223456; 18 const int MOD=1e9+7; 19 20 21 const int CHARSET=26,BASE=‘a‘,MAX_NODE=10000*20*26+5000; 22 struct Trie { 23 int tot,root,child[MAX_NODE][CHARSET]; 24 int flag[MAX_NODE],num[MAX_NODE]; 25 Trie(){ 26 init(); 27 } 28 void init(){ 29 tot=0; 30 root=newNode(); 31 } 32 int newNode() { 33 ++tot; 34 memset(child[tot],0,sizeof(child[tot])); 35 flag[tot]=0; 36 num[tot]=-1; 37 return tot; 38 } 39 void insert(const char *str,int id){ 40 int *cur=&root; 41 for (const char *p=str;*p;++p){ 42 cur=&child[*cur][*p-BASE]; 43 if (*cur==0){ 44 *cur=newNode(); 45 } 46 if (num[*cur]!=id) 47 flag[*cur]++; 48 num[*cur]=id; 49 } 50 } 51 int query(const char *str){ 52 int *cur=&root; 53 for (const char *p=str;*p&&(*cur);++p){ 54 cur=&child[*cur][*p-BASE]; 55 } 56 return flag[*cur]; 57 } 58 }trie; 59 int main () { 60 int n; 61 scanf("%d",&n); 62 char s[120]; 63 for (int i=1;i<=n;i++) { 64 scanf("%s",s); 65 int len=strlen(s); 66 for (int j=0;j<len;j++) 67 trie.insert(s+j,i); 68 } 69 int Q; 70 scanf("%d",&Q); 71 while (Q--) { 72 scanf("%s",s); 73 int ret=trie.query(s); 74 printf("%d\n",ret); 75 } 76 return 0; 77 }
标签:
原文地址:http://www.cnblogs.com/micrari/p/4951439.html