POJ - 3691 DNA repair (AC自动机+DP)

题意:(换了一种描述,其实是一样的题)

POJ - 3691 DNA repair (AC自动机+DP)_第1张图片

 POJ - 3691 DNA repair (AC自动机+DP)_第2张图片

 分析:

首先对与这种题的题问,可以很明显地感觉到DP

因为很多模式串,所以考虑多模式匹配的AC自动机算法。

首先考虑建立fail树,跟正常的ac自动机的fail树其实是一样的,只不过多了一个东西,就是对于这种情况:

以下面这两个字符串建立fail树为例:

CD

ABCDAB

那么很显然第二个字符串中间的CD也是非法状态。所以对于建立fail树的时候也要对这种情况进行统计,(其实也很好写,看下代码就清楚了)。

下面介绍dp:

首先确定dp方程,

dp[i][j] 表示前 i 个字符 在 AC 自动机上的状态为 j 的时候满足条件的最小改变次数。

可能有点抽象,下面我举个例子就清楚了。

只拿AB举例:

比如给出的样例是:

1

AB

ABABAB

那么:

前1个字符  最小改变次数

    A                   0

    B                   1

 

前2个字符  最小改变次数

    AB                 inf  (当前状态非法)

    AA                1

   BB                1

   BA                 2

。。。。。。。。。。。。。。。。。。依次类推

对于不存在的节点其实就是0节点没就像上面一开始就修改的B一样。

可能还会有疑惑,为什么可以看作0节点,那如果当前修改为BAB,这个状态非法,这样也可以直接统计出来并且也不会出错。

所以这样每个状态都枚举了一遍,最后统计最小值即可。

//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include //accumulate

#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair
#define pdd pair
#define pll pair
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define rush() int T;scanf("%d",&T);while(T--)
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define pf(a) printf("%d\n",a)
#define pf2(a,b) printf("%d %d\n",a,b)
#define pf3(a,b,c) printf("%d %d %d\n",a,b,c)
#define debug(x) cout<<#x<<": "< q;
        q.push(root);
        while(!q.empty()){
            int p=q.front();q.pop();
            for(int i=0;i<4;i++){
                if(~next[p][i]){
                    if(p==root) fail[next[p][i]]=root;
                    else fail[next[p][i]]=next[fail[p]][i];
                    q.push(next[p][i]);
                    cnt[next[p][i]]+=cnt[fail[next[p][i]]];
                }else{
                    if(p==root) next[p][i]=root;
                    else next[p][i]=next[fail[p]][i];
                }
            }
        }
    }
    int solve(string s){
        dp[0][0]=0;
        for(int i=1;i<=s.size();i++){
            for(int j=0;j>n&&n){
        mm(dp,inf);
        ac.clear();
        string s;
        rep(i,1,n) {
            cin>>s;
            for(int i=0;i>s;
        for(int i=0;i

 

你可能感兴趣的:(字符串,动态规划)