poj 2945 Find the clones (tire树)

本文介绍了一种使用字典树结构解决DNA序列匹配与克隆计数问题的方法,通过构建字典树并保留每个节点的计数信息,实现了高效地统计未克隆和已克隆个体的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:输入一些人的DNA序列,输出的意思是,第一行代表没有被克隆的人数,第二行是被克隆一次的人数。。。依此类推。

思路:字典树,建树的时候保留DNA最后一个字母的count信息,存在ans[]数组里,这里有个技巧,一、没克隆的++。二、克隆过的++,同时上一个克隆的次数--;

代码比较搓,5000MS限制,4000MS+水过,同时内存超了,释放了下内存,AC了。

#include<iostream>
using namespace std;
struct node
{
  int count;
  node *next[26];
  node()
  {
    count=0;
    for(int i=0;i<26;i++)
    next[i]=NULL;
  }
};
int ans[20005];
void insert(node *root,char *word,int j)
{
  node *l=root;
  int branch,i=0;
  while(word[i]!='\0')
  {
    branch=word[i]-'A';
    if(l->next[branch]) {l->next[branch]->count++;}
    else l->next[branch]=new node();
    l=l->next[branch];
    i++;
    //printf("a  %d  \n",l->count);
  }
  //printf("%d\n",l->count);
  if(l->count!=0)
  {
    ans[l->count]++;
    ans[l->count-1]--;
  }
  else ans[l->count]++;//处理ans数组的技巧,灵感啊~哈哈
}
void dfs_free(node *root)
{
  for(int i=0;i<26;i++)
    if(root->next[i]!=NULL)
    dfs_free(root->next[i]);
    free(root);
}
int main()
{
  int N,M,i,flag;
  char word[25],s[25];
  while(scanf("%d%d",&N,&M)!=EOF)
  {
    if(N==0&&M==0)  break;
    node *root=new node();
    memset(ans,0,sizeof(ans));
    for(i=0;i<N;i++)
    {
      scanf("%s",word);
      insert(root,word,i);
    }
    dfs_free(root);//递归的释放内存
    int sum=0;
    for(i=0;i<N;i++)
    {
      printf("%d\n",ans[i]);
    }
  }
}


看到了个快排版本的贴出来哈。。是依然博客的   地址在我的大牛博客的连接里找。

#include<iostream>
#include<algorithm>
using namespace std;
struct Str{
    char DNA[25];   
}S[20010];
//int cmp(Str a,Str b) {
//    if (strcmp(a.DNA,b.DNA) < 0) return 1;
//    return 0;    
//}
bool operator < (const Str &a , const Str &b) {
    if (strcmp(a.DNA , b.DNA) < 0) return 1;
    return 0;    
}
int main() {
    int m , n;
    int num[20010];
    while (scanf("%d%d",&m,&n)!=EOF) {
        for (int i = 0 ; i < m ; i ++) {
            scanf("%s",S[i].DNA);    
        }
        sort(S, S+m); 
        memset(num , 0 ,sizeof(num));
        int head = 0 , tail = 1;
        while(tail < m) {  //这个技巧值得借鉴 
            if (strcmp(S[head].DNA , S[tail].DNA)!=0) {
                num[tail - head] ++;
                head = tail;        
            }
            tail ++;    
        }   
        num[tail - head] ++;
        // count = 1;
        //或者  for (1--n) 
        //    if  S[i-1].DNA == S[i].DNA  count++;
        //    else  num[count] ++ ;  count = 1;  
        for (int i = 1 ; i <= m ; i ++) {
            printf("%d\n",num[i]);    
        }
    }    
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值