现在的位置: 首页 > 综合 > 正文

hdu2457 DNA repair

2013年09月02日 ⁄ 综合 ⁄ 共 1610字 ⁄ 字号 评论关闭

hdu2457 DNA repair

题目大意:给出n个模式串,和一个母串,问可以改变最少多少个母串中的字符可以使得母串不包含模式串

dp[i][j]表示长度为i,走到j号节点时,最少修改几次

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std ;

const int maxn = 1111 ;
short dp[maxn][1111] ;

int min ( int a , int b ) { return a < b ? a : b ; }

class AC_auto
{

private :
    int tot ;
    int c[4][maxn] ;
    int id[maxn] ;
    int fail[maxn] ;
    queue<int> Q ;
public :

    int new_node ()
    {
        int i ;
        for ( i = 0 ; i < 4 ; i ++ ) c[i][tot] = 0 ;
        id[tot] = 0 ;
        fail[tot] = 0 ;
        return tot ++ ;
    }

    void init () { tot = 0 ; while ( !Q.empty () ) Q.pop () ; new_node () ; }
    
    int get_k ( char v )
    {
        int k ;
        switch ( v )
        {
        case 'A' : k = 0 ; break ;
        case 'G' : k = 1 ; break ;
        case 'C' : k = 2 ; break ;
        case 'T' : k = 3 ; break ;
        }
        return k ;
    }

    void insert ( char *s )
    {
        int now = 0 ;
        for ( ; *s ; s ++ )
        {
            int k = get_k ( *s ) ;
            if ( !c[k][now] ) c[k][now] = new_node () ;
            now = c[k][now] ;
        }
        id[now] = 1 ;
    }

    void get_fail ()
    {
        int u = 0 , i , j , e ;
        for ( i = 0 ; i < 4 ; i ++ ) if ( c[i][u] ) Q.push ( c[i][u] ) ;
        while ( !Q.empty () )
        {
            u = Q.front () ;
            Q.pop () ;
            for ( i = 0 ; i < 4 ; i ++ )
            {
                if ( !c[i][u] )
                {
                    c[i][u] = c[i][fail[u]] ;
                    continue ;
                }
                j = fail[u] , e = c[i][u] ;
                fail[e] = c[i][j] ;
                id[e] |= id[fail[e]] ;
                Q.push ( e ) ;
            }
        }
    }

    void work ( char *s )
    {
        int i , j , l ;
        int n = strlen ( s + 1 ) ;
        for ( i = 0 ; i <= n ; i ++ )
            for ( j = 0 ; j < tot ; j ++ )
                dp[i][j] = -1 ;
        dp[0][0] = 0 ;
        for ( i = 0 ; i < n ; i ++ )
            for ( j = 0 ; j < tot ; j ++ )
            {
                if ( dp[i][j] == -1 ) continue ;
                int k = get_k ( s[i+1] ) ;
                for ( l = 0 ; l < 4 ; l ++ )
                {
                    int add = 0 ;
                    if ( l != k ) add = 1 ;
                    int e = c[l][j] ;
                    if ( !id[e] ) 
                    {
                        if ( dp[i+1][e] == -1 ) dp[i+1][e] = dp[i][j] + add ;
                        else dp[i+1][e] = min ( dp[i+1][e] , dp[i][j] + add ) ;
                    }
                }
            }
        int ans = -1 ;
        for ( i = 0 ; i < tot ; i ++ )
        {
            if ( dp[n][i] == -1 ) continue ;
            if ( ans == -1 ) ans = dp[n][i] ;
            else ans = min ( ans , dp[n][i] ) ;
        }
        printf ( "%d\n" , ans ) ;
    }

} ac ;

char s[maxn] ;

int main ()
{
    int n , i ;
    int cas = 0 ;
    while ( scanf ( "%d" , &n ) != EOF )
    {
        if ( n == 0 ) break ;
        cas ++ ;
        ac.init () ;
        for ( i = 1 ; i <= n ; i ++ )
        {
            scanf ( "%s" , s ) ;
            ac.insert ( s ) ;
        }
        ac.get_fail () ;
        scanf ( "%s" , s + 1 ) ;
        printf ( "Case %d: " , cas ) ;
        ac.work ( s ) ;
    }
}

抱歉!评论已关闭.