• poj 3691 DNA repair AC自动机+DP


    题意:给定n个疾病DNA序列,和一个待修复序列str。用最小的次数修改待修复序列,使其不含疾病DNA序列。


    思路:AC自动机+DP

    建自动机 并加上虚拟节点 每一个节点作为一个dp第二维状态

    dp[i][j] 表示修复str前i个字符,且当前状态为j的最小修改次数

    str从1开始 AC自动 树根标号为0 dp[0][0]=0;

    dp[i+1][j]=min(dp[i+1][j],dp[i][j]+(j代表的当前字符!=str[i+1]))

    ans=min(ans,dp[m-1][j]);  (0<=j<top) top是自动机节点数

      1 #include<iostream>
    2 using namespace std;
    3 #define MAXN 1002
    4 int dp[MAXN][MAXN];
    5 struct node
    6 {
    7 int id,name;
    8 bool end;
    9 node *next[4],*father,*failink;
    10 };
    11 int n,m,top=0;
    12 node *head;
    13 node memo[MAXN];
    14 node *Q[MAXN];
    15 char str[MAXN];
    16 int get(char c)
    17 {
    18 switch(c)
    19 {
    20 case 'A': return 0;
    21 case 'G': return 1;
    22 case 'C': return 2;
    23 case 'T': return 3;
    24 }
    25 }
    26 void insert(node *t,char c[],int i)
    27 {
    28 if(i==strlen(c))
    29 {
    30 t->end=1; return ;
    31 }
    32 int x=get(c[i]);
    33 if(t->next[x]==NULL)
    34 {
    35 //cout<<i<<" "<<top<<" "<<x<<endl;
    36 node *p=&memo[top]; p->id=top++; p->father=t; p->name=x;
    37 t->next[x]=p;
    38 }
    39 insert(t->next[x],c,i+1);
    40 }
    41 void set_fail_link()
    42 {
    43 int i,j;
    44 int front,behind;
    45 Q[front=behind=0]=head;
    46 node *p,*t;
    47 while(front<=behind)
    48 {
    49 p=Q[front++];
    50 if(p->father==head) p->failink=head;
    51 else if(p!=head)
    52 {
    53 t=p->father->failink;
    54 int x=p->name;
    55 //cout<<x<<endl;
    56 while(1)
    57 {
    58 if(t->next[x]!=NULL)
    59 {
    60 if(t->next[x]->end) p->end=1;
    61 p->failink=t->next[x];
    62 break;
    63 }
    64 else if(t==head)
    65 {
    66 p->failink=t; break;
    67 }
    68 else t=t->failink;
    69 }
    70 }
    71 for(i=0;i<4;i++)
    72 {
    73 if(p->next[i]!=NULL) Q[++behind]=p->next[i];
    74 else //建立虚拟节点
    75 {
    76 if(p==head) p->next[i]=p;
    77 else p->next[i]=p->failink->next[i];
    78 }
    79 }
    80 }
    81 }
    82 int dynamic_programming()
    83 {
    84
    85 int m=strlen(str);
    86
    87 memset(dp,0x3f,sizeof(dp));
    88 int i,j,k;
    89 node *p,*q;
    90 dp[0][0]=0;
    91 for(i=0;i<m-1;i++)
    92 for(j=0;j<top;j++)
    93 if(dp[i][j]<MAXN)
    94 for(k=0;k<4;k++)
    95 {
    96 p=&memo[j];
    97 q=p->next[k];
    98 if(q->end==0)
    99 dp[i+1][q->id]=min(dp[i+1][q->id],dp[i][j]+(k!=get(str[i+1])));
    100 }
    101 int ans=MAXN+1;
    102 for(j=0;j<top;j++) ans=min(ans,dp[m-1][j]);
    103 if(ans>MAXN) return -1;
    104 return ans;
    105 }
    106 int main()
    107 {
    108 char c[21];
    109 int i,j=0;
    110 scanf("%d",&n);
    111 str[0]='1';
    112 while(n!=0)
    113 {
    114 j++;
    115 top=0;
    116 memset(memo,0,sizeof(memo));
    117 head=&memo[top]; head->id=top++;
    118 for(i=1;i<=n;i++)
    119 {
    120 scanf("%s",c);
    121 insert(head,c,0);
    122 }
    123 scanf("%s",str+1);
    124 set_fail_link();
    125 printf("Case %d: %d\n",j,dynamic_programming());
    126 scanf("%d",&n);
    127 }
    128 return 0;
    129 }
  • 相关阅读:
    栈的实现方式
    复合和继承
    循环链表和双向链表
    抽象类和接口
    private构造器和单例模式
    内部类
    关于初始化和清理
    多态的理解
    幾個小知識
    Youth
  • 原文地址:https://www.cnblogs.com/myoi/p/2345035.html
Copyright © 2020-2023  润新知