https://vjudge.net/problem/POJ-2945
题意:
给出n个长度相同的DNA序列,如果一个DNA序列出现过两次,那么就有说明它被复制了一次。问被复制0次,1次,2次……n-1次的DNA序列分别有多少个。
思路:
可以利用字典树的方法做,用map目测会超时。因为一个字符串是它自己本身的假前缀,所以把每一个字符串的前缀数量-1,就是它被复制的数目。这题学到了一个技巧,统计的时候,已经统计过的要跳开,一开始用map判断超时了,之后想到用sort对char类型的字符串进行排序,但是sort是不能对char的字符串进行排序。但是,我们有结构体啊,把字符串封装在一个结构体中,自己写一个cmp函数就完美的解决了这个问题。这题还是字典树模板用上啦。一定记住最后要释放内存啊。QAQ
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 6 int a[20005]; 7 8 const int maxn = 26; 9 10 struct str 11 { 12 char s[25]; 13 }b[20005]; 14 15 bool cmp(str aa,str bb) 16 { 17 return strcmp(aa.s,bb.s) < 0; 18 } 19 20 struct trie 21 { 22 trie *next[maxn]; 23 24 int flag; 25 26 trie() 27 { 28 flag = 1; 29 memset(next,NULL,sizeof(next)); 30 } 31 }*root; 32 33 void insert(char *str) 34 { 35 int len = strlen(str); 36 trie *p = root,*q; 37 38 for (int i = 0;i < len;i++) 39 { 40 int id = str[i] - 'A'; 41 42 if (p -> next[id] == NULL) 43 { 44 q = new trie(); 45 p -> next[id] = q; 46 p = p -> next[id]; 47 } 48 else 49 { 50 p = p->next[id]; 51 52 ++(p->flag); 53 } 54 } 55 } 56 57 int query(char *str) 58 { 59 int len = strlen(str); 60 trie *p = root; 61 62 for (int i = 0;i < len;i++) 63 { 64 int id = str[i] - 'A'; 65 66 p = p -> next[id]; 67 68 if (p == NULL) return 0; 69 } 70 71 return p->flag; 72 } 73 74 void Free(trie* t) 75 { 76 if (t == NULL) return; 77 78 for (int i = 0;i < maxn;i++) 79 { 80 if (t -> next[i]) Free(t->next[i]); 81 } 82 83 delete(t); 84 } 85 86 87 88 int main() 89 { 90 int n,m; 91 92 while (scanf("%d%d",&n,&m) != EOF) 93 { 94 if (m == 0 && n == 0) break; 95 96 memset(a,0,sizeof(a)); 97 98 root = new trie(); 99 100 for (int i = 0;i < n;i++) 101 { 102 scanf("%s",b[i].s); 103 insert(b[i].s); 104 } 105 106 sort(b,b+n,cmp); 107 108 //for (int i = 0;i < n;i++) 109 //printf("%s ",b[i].s); 110 111 int rs = query(b[0].s); 112 113 char ss[25];strcpy(ss,b[0].s); 114 115 a[rs-1]++; 116 117 for (int i = 1;i < n;i++) 118 { 119 if (strcmp(ss,b[i].s) == 0) continue; 120 121 strcpy(ss,b[i].s); 122 123 rs = query(b[i].s); 124 125 a[rs-1]++; 126 } 127 128 129 for (int i = 0;i < n;i++) 130 { 131 printf("%d ",a[i]); 132 } 133 134 Free(root); 135 } 136 137 return 0; 138 }