HDU 2547 AC+DP

题意    就是将一个含有 病毒的字符串  修改成一个不含病毒的字符串;  

方法    由于  只有 四种字符,那么状态就很少了,每步只有四个状态可达,上一个状态只有  1000多种,所以能承受;

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;

struct date
{
    date *next[5],*fail;
    int in,flag;
}tree[1123],*que[1123],*root;
int total,head,tail,hash[556];
char str[1004];

date *creat_node( )
{
    for( int i = 0; i <= 4; i++ )
    tree[total].next[i] = NULL;
    tree[total].fail    = NULL;
    tree[total].in      = total;
    tree[total].flag    = false;
    return &tree[total++];
}

void inint( )
{
    hash[int('A')] = 1;  hash[int('C')] = 2;
    hash[int('G')] = 3;  hash[int('T')] = 4;
    head = tail = total = 0;
    root = creat_node();
    root->fail = root;
}

void insert( char *word )
{
    date *temp = root;
    while( *word )
    {
        int num = hash[int(*word)];
        if( temp->next[num] == NULL )
            temp->next[num] = creat_node();
        temp = temp->next[num];
        word++;
    }
    temp->flag = true;
}

void build_AC( )
{
    que[tail++] = root;
    while( tail > head )
    {
        date *temp = que[head++];
        for( int i = 1; i <= 4; i++ )
        if( temp->next[i] != NULL )
        {
            if( temp == root ) temp->next[i]->fail = root;
            else               temp->next[i]->fail = temp->fail->next[i];
            temp->next[i]->flag = (temp->next[i]->flag | temp->next[i]->fail->flag)|temp->flag;
            que[tail++] = temp->next[i];
        }
        else
        {
            if( temp == root )temp->next[i] = root;
            else              temp->next[i] = temp->fail->next[i];
        }
    }
}
int  dp[1123][1123];
void DP( )
{
    int i,j,k,len = strlen( str );
    for( i = 0; i <= 1120;  i++ )
    for( j = 0; j <= 1120;  j++ )
        dp[i][j] = 199999999;
    dp[0][0] = 0;
    for( i = 1; i <= len  ; i++ )
    for( j = 0; j <  total; j++ )
    for( k = 1; k <= 4; k++ )
    if( !tree[j].next[k]->flag )
    {
           if( hash[int(str[i-1])] == k  )
                dp[i][tree[j].next[k]->in] = min( dp[i][tree[j].next[k]->in],dp[i-1][j] );
           else dp[i][tree[j].next[k]->in] = min( dp[i][tree[j].next[k]->in],dp[i-1][j] + 1 );
    }
    int res = 199999999;
    for( i = 0; i < total; i++ )
    if(  tree[i].flag == false )
       res = min( res,dp[len][i] );
    if( res == 199999999 ) printf("-1\n");
    else                   printf("%d\n",res);
}

int main( )
{
    int N,i,k = 1;
    while( scanf("%d",&N) && N )
    {
        inint( );
        for( i = 1; i <= N; i++ )
        scanf("%s",&str),insert( str );
        build_AC( );
        scanf("%s",&str);
        printf("Case %d: ",k++);
        DP( );
    }
}
原文地址:https://www.cnblogs.com/wulangzhou/p/3016812.html