程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ 3691 DNA repair 基於AC自動機的DP

POJ 3691 DNA repair 基於AC自動機的DP

編輯:C++入門知識

POJ 3691 DNA repair 基於AC自動機的DP


dp[i][j] 表示長度為 i 的前綴到達第 j 個節點的最小更改數目。

很顯然有dp[0][0] = 0;

dp[ i ][ j ] = min(dp[ i ][ j ],dp[i-1][k] + (j == k ? 0 : 1)),當且僅當j,k滿足下列條件時。

j 不為某條模式串的末節點 且 j 到 root 的由失敗指針組成的路徑上無末節點。

j 是k的兒子節點 或者 j 的父節點可由 k 沿著失敗指針找到。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f

using namespace std;

const int MAXN = 4;

struct N
{
    int next[MAXN],flag,fail;
} st[1010];

int Top;

int sel(char c)
{
    if(c == 'A')
        return 0;
    if(c == 'G')
        return 1;
    if(c == 'C')
        return 2;
    return 3;
}

int creat()
{
    memset(st[Top].next,-1,sizeof(st[Top].next));
    st[Top].fail = -1,st[Top].flag = 0;
    return Top++;
}

int dp[1010][1010];

char s[1010];

void Get_Trie(int root,char *s)
{
    int site = 1;

    while(s[site] != '\0')
    {
        if(st[root].next[sel(s[site])] == -1)
            st[root].next[sel(s[site])] = creat();
        root = st[root].next[sel(s[site])];
        ++site;
    }

    st[root].flag = 1;
}

int Get_Fail(int site,int tar)
{
    while(site != -1 && st[site].next[tar] == -1)
        site = st[site].fail;
    if(site == -1)
        return 0;
    return st[site].next[tar];
}

queue q;

void Get_Fail(int root)
{
    q.push(root);

    st[root].fail = -1;

    int f;

    while(q.empty() == false)
    {
        f = q.front();
        q.pop();

        for(int i = 0; i < MAXN; ++i)
        {
            if(st[f].next[i] != -1)
            {
                st[st[f].next[i]].fail = Get_Fail(st[f].fail,i);
                q.push(st[f].next[i]);
            }
        }
    }
}

bool Is_Safe(int site)
{
    if(site == -1)
        return true;
    if(st[site].flag || Is_Safe(st[site].fail) == false)
        return false;
    return true;
}

int Is_Safe(int site,int tar)
{

    if(site == -1)
        return 0;
    if(st[site].next[tar] != -1)
    {
        if(st[st[site].next[tar]].flag != 0 || Is_Safe(st[site].next[tar]) == false)
            return -1;
        return st[site].next[tar];
    }
    return Is_Safe(st[site].fail,tar);
}

void Match(int root,char *s)
{
    memset(dp,INF,sizeof(dp));
    dp[0][0] = 0;

    int site,i,j,tmp;

    for(site = 1; s[site] != '\0'; ++site)
    {
        for(i = 0; i < Top; ++i)
        {
            if(dp[site-1][i] == INF)
                continue;

            for(j = 0; j < 4; ++j)
            {
                if(st[i].next[j] != -1 && st[st[i].next[j]].flag != 0)
                    continue;
                if(st[i].next[j] != -1 && Is_Safe(st[i].next[j]))
                {
                    dp[site][st[i].next[j]] = min(dp[site][st[i].next[j]],dp[site-1][i] + (j == sel(s[site]) ? 0 : 1));
                    continue;
                }

                tmp = Is_Safe(i,j);

                if(tmp == -1)
                    continue;
                dp[site][tmp] = min(dp[site][tmp],dp[site-1][i] + (j == sel(s[site]) ? 0 : 1));
            }
        }
    }
}

int main()
{
    int i,n;

    int icase = 1;

    int root;

    while(scanf("%d",&n) && n)
    {
        Top = 0;
        root = creat();

        for(int i = 1; i <= n; ++i)
        {
            scanf("%s",s+1);
            Get_Trie(root,s);
        }

        Get_Fail(root);

        scanf("%s",s+1);

        Match(root,s);

        int anw = INF,len = strlen(s+1);

        for(i = 0; i < Top; ++i)
            anw = min(anw,dp[len][i]);
        printf("Case %d: %d\n",icase++,anw == INF ? -1 : anw);
    }

    return 0;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved