zoukankan      html  css  js  c++  java
  • Cerc2014 Virus synthesis

    题目描述:

    你要用ATGC四个字母用两种操作拼出给定的串: 
    1.将其中一个字符放在已有串开头或者结尾 
    2.将已有串复制,然后reverse,再接在已有串的头部或者尾部 
    一开始已有串为空。求最少操作次数。 
    len<=100000
    题解:
    PAM+dp。
    先建出PAM,然后对于每一个偶树上的串,满足:
    1.得到上一个串时一定是先延长后倍增,所以dp[ i ] = dp[ las ] + 1;
    2.先得到一个长<=len/2的串然后延长+倍增,所以dp[ i ] = dp[ pre ] + len/2 - len0 + 1;
    代码:
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100050
    int T,n;
    char s[N];
    struct pnt
    {
        int pre,len,trs[4];
        void clear()
        {
            pre=len=trs[0]=trs[1]=trs[2]=trs[3]=0;
        }
    }p[N];
    int ci(char c)
    {
        if(c=='A')return 0;
        if(c=='G')return 1;
        if(c=='C')return 2;
        return 3;
    }
    int dp[N],ans;
    struct PAM
    {
        int tot,las;
        void res()
        {
            p[0].clear(),p[1].clear();
            tot=las=1;
            p[0].pre=p[1].pre=1;
            p[1].len=-1;
            memset(dp,0x3f,sizeof(dp));
        }
        bool mis(int i,int x)
        {
            return s[i]!=s[i-p[x].len-1];
        }
        void insert(int i)
        {
            int lp = las;
            while(mis(i,lp))lp=p[lp].pre;
            int c = ci(s[i]);
            if(!p[lp].trs[c])
            {
                int np = ++tot;
                p[np].clear();
                int tmp = p[lp].pre;
                while(mis(i,tmp))tmp=p[tmp].pre;
                p[np].pre=p[tmp].trs[c];
                p[np].len=p[lp].len+2;
                p[lp].trs[c]=np;
            }
            las=p[lp].trs[c];
        }
        int fa[N][21];
        void init()
        {
            for(int i=0;i<=tot;i++)fa[i][0]=p[i].pre;
            for(int i=1;i<=20;i++)
                for(int j=0;j<=tot;j++)
                    fa[j][i]=fa[fa[j][i-1]][i-1];
        }
        int get_mid(int u)
        {
            int ret = u;
            for(int i=20;i>=0;i--)
                if(p[fa[ret][i]].len*2>=p[u].len)ret=fa[ret][i];
            while(p[ret].len&1||p[ret].len*2>p[u].len)ret=p[ret].pre;
            return ret;
        }
        void DP()
        {
            dp[0]=0;
            queue<int>q;
            for(int i=0;i<4;i++)
                if(p[0].trs[i])
                {
                    dp[p[0].trs[i]]=2;
                    q.push(p[0].trs[i]);
                }
            ans = n;
            while(!q.empty())
            {
                int u = q.front();
                q.pop();
                int mid = get_mid(u);
                dp[u]=min(dp[u],dp[mid]+p[u].len/2-p[mid].len+1);
                ans=min(ans,dp[u]+n-p[u].len);
                for(int i=0;i<4;i++)
                    if(p[u].trs[i])
                    {
                        dp[p[u].trs[i]]=dp[u]+1;
                        q.push(p[u].trs[i]);
                    }
            }
        }
    }pam;
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%s",s+1);
            n = strlen(s+1);
            pam.res();
            for(int i=1;i<=n;i++)
                pam.insert(i);
            pam.init();
            pam.DP();
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    设计模式 --> (3)策略模式
    设计模式 --> (2)单例模式
    设计模式 --> (1)工厂模式
    Algorithm --> 十大排序算法
    Algorithm --> 求阶乘末尾0的个数
    网络通信 --> epoll用法
    数据库 --> sqlite3之api使用
    网络通信 --> select()用法
    网络通信 --> TCP三次握手和四次挥手
    『转载』周立功:专注的力量成就梦想
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10127214.html
Copyright © 2011-2022 走看看