POJ 3691 DNA Repair AC自动机

/*
TRIE结构,在使用前必须调用初始化init()!!!
主要调用Ins,ser,返回值都是TRIE中的下标;del,返回有无字符串(删除成功否)
*/
#include<stdio.h>
#include<iostream>
#include<memory.h>
#include<queue>
using namespace std;
const int CTNUM = 26;  //储存字母的数目
const int STRNUM = 15000; //节点数目,绝对不能少于给定的字符串数目,一般给大点
const int MINCHAR='A';  //大小写分辨,如果混用或者不连续的话需要有对应的hash函数
struct TRIE
{
 int son[CTNUM];
 int count;
 int father;
}trie[STRNUM];
int fail[STRNUM];
int TNUM=1;
queue<int> q;
char s[200][200],ss[2000];
int dp[2000][2000],n;
#define INT_MAX 10000000
void init()
{
 memset(&trie[0],0,sizeof(TRIE));
 memset(&trie[1],0,sizeof(TRIE));
 TNUM=2;
}
int Ins(char *str,int len)
{
 int i;
 int cur=1;
 for(i=0;i<len;i++)
 {
  if( !trie[cur].son[str[i]-MINCHAR] )
  {
   memset( &trie[TNUM],0,sizeof(TRIE) );
   trie[TNUM].father=cur;
   cur=trie[cur].son[str[i]-MINCHAR]=TNUM++;
  }
  else cur=trie[cur].son[str[i]-MINCHAR];
  if (trie[cur].count>0) return cur;
 }
 trie[cur].count++;
 return cur;
}
void calc_fail()
{
 int i,k,p;
 fail[0]=0;
 fail[1]=0;
 memset(fail,0,sizeof(fail));
 while(!q.empty()) q.pop();
 q.push(1);
 while(!q.empty())
 {
  i=q.front();
  q.pop();
  if (trie[fail[i]].count==1)
   trie[i].count=1;
  for(k='A'-MINCHAR;k<='D'-MINCHAR;k++)
  if (trie[i].son[k]!=0)
  {
   
                  int p=fail[i];
      while(p!=0&&trie[p].son[k]==0)
       p=fail[p];
      if (!p) fail[trie[i].son[k]]=1;
      else
      fail[trie[i].son[k]]=trie[p].son[k];
   q.push(trie[i].son[k]);
  }
 }
}

int min(int x,int y)
{
 if (x<y) return x;
 else return y;
}
int main()
{
   int i,j,t,ans,k,u,next,l;
   bool fl;
   u=0;
   while(scanf("%d",&n)!=EOF)
   {
    u++;
    if (n==0) break;
    for(i=1;i<=n;i++)
    {
    scanf("%s",&s[i]);
    for(j=0;j<strlen(s[i]);j++)
     if (s[i][j]=='G') s[i][j]='B';
     else if (s[i][j]=='T') s[i][j]='D';
    }
    scanf("%s",&ss);
       for(j=0;j<strlen(ss);j++)
     if (ss[j]=='G') ss[j]='B';
     else if (ss[j]=='T') ss[j]='D';
       init();
      for(i=1;i<=n;i++)
     Ins(s[i],strlen(s[i]));
    calc_fail();
    l=strlen(ss);
       for(i=0;i<=l;i++)
     for(j=0;j<=TNUM;j++)
      dp[i][j]=INT_MAX;
    dp[0][1]=0; 
    for(i=0;i<l;i++)
     for(j=1;j<TNUM;j++)
      if (trie[j].count==0)
             for(k='A';k<='D';k++)
    {
     t=j;
     while(t!=0&&trie[t].son[k-MINCHAR]==0)
      t=fail[t];
     if (t==0) next=1;
     else
     next=trie[t].son[k-MINCHAR];
     if (trie[next].count==0)
     dp[i+1][next]=min(dp[i+1][next],dp[i][j]+(k!=ss[i]));
    }
    ans=INT_MAX;
    for(j=1;j<TNUM;j++)
     if (trie[j].count==0)
     if (dp[l][j]<ans)
      ans=dp[l][j];
  cout<<"Case "<<u<<": ";
  if (ans!=INT_MAX)
       cout<<ans<<endl;
  else cout<<"-1"<<endl;
   }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值