| Time Limit: 5000MS | Memory Limit: 65536K | |
| Total Submissions: 7140 | Accepted: 2655 |
Description
Input
Output
Sample Input
9 6
AAAAAA
ACACAC
GTTTTG
ACACAC
GTTTTG
ACACAC
ACACAC
TCCCCC
TCCCCC
0 0
Sample Output
1
2
0
1
0
0
0
0
0
Hint
Source
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int const MAX = 20005; //n最大
int const LEN = 25; //m最大
int change(char ch) //将ACGT转为0123
{
if(ch == 'A')
return 0;
if(ch == 'C')
return 1;
if(ch == 'G')
return 2;
return 3;
}
struct node
{
node* child[4]; //孩子结点,4叉字典树
int cnt; //同一个单词出现的次数
bool end; //判断是否为叶子结点及是否为某个单词的最后一个字母
}Tree[MAX * LEN];
int cnt = 0; //除去根结点的结点总数
int ans[MAX]; //ans[i] = j 表示重复了i次的不同基因有j个
char s[MAX][LEN];
inline void Init(node *p) //初始化根或子树
{
memset(p -> child, NULL, sizeof(p -> child));
p -> end = false;
p -> cnt = 0;
}
void Insert(node *p, char *s)
{
for(int i = 0; s[i] != '\0'; i++)
{
int idx = change(s[i]); //将字母转变为下标序号
if(p -> child[idx] == NULL) //若孩子为空,即改前缀未出现,则插入字典树
{
cnt++; //多一个结点,计数器加1
p -> child[idx] = Tree + cnt; //插入该结点
Init(p -> child[idx]); //初始化以该结点为根的子树
}
p = p -> child[idx]; //转向下一结点
}
if(p -> end) //表示该单词出现过
{
p -> cnt++;
return;
}
p -> end = true; //记录一个完整的单词
p -> cnt = 1; //该单词出现了一次
}
int main()
{
int n, m;
while(scanf("%d %d", &n, &m) != EOF && (n + m))
{
node *root = Tree;
Init(root);
cnt = 0;
memset(ans, 0, sizeof(ans));
for(int i = 0; i < n; i++)
{
scanf("%s", s[i]);
Insert(root, s[i]);
}
for(int i = 1; i <= cnt; i++)
if(Tree[i].end) //若该单词(序列)出现过
ans[Tree[i].cnt]++; //记录重复了cnt次的单词的个数
for(int i = 1; i <= n; i++)
printf("%d\n", ans[i]);
}
}
POJ 2945 Find the Clones (Trie树)
原文地址:http://blog.csdn.net/tc_to_top/article/details/43915685