[AC自动机+dp+变进制状压] hdu 3341 Lost's revenge

题意思路摘自大神:http://www.cppblog.com/menjitianya/archive/2014/07/11/207604.html#207622

题意:给定N(N <= 50)个长度不超过10的模式串(ACGT串),再给定一个长度为M(M <= 40)的目标串S,求将目标串重排列,使得它包含最多的模式串,求这个最多的数目。

题解:利用模式串建立trie图,trie图上最多有500个结点( N*10 ),然后朴素的思想就是用S(i, iA, iC, iG, iT)表示在i状态下,拥有iA个A、iC个C、iG个G、iT个T的串拥有的最多的模式串的个数,但是iA, iC, iG, iT的取值均是[0, 40],所以我们需要把状态压缩一下,我们知道当四种字符都取10的时候可以让状态数达到最大,即114 = 14641, 所以可以令MaxA

MaxC、MaxG、MaxT分别表示四种字符出现的个数,那么T字符的权值为1,G字符的权值为(Max+ 1),C字符的权值为(Max+ 1) *(Max+ 1),A字符的权值为(Max+ 1) *(Max+ 1) *(Max+ 1),进行进制压缩之后总的状态数不会超过114,可以用DP[i][j]表示在trie的i号结点时ACGT四个字符个数的压缩状态为j时的字符串包含模式串的最多数目,然后就是进行O(4*500*114)的状态转移了。

代码:

#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"map"
#include"iostream"
using namespace std;
int triecont;
char fuck[55];
struct trie
{
    int mark,id;
    trie *next[6],*fail;
    trie()
    {
        mark=id=0;
        memset(next,0,sizeof(next));
        fail=NULL;
    }
};
trie *root,*node[520];
int getid(char x)
{
    if(x=='A') return 0;
    if(x=='C') return 1;
    if(x=='G') return 2;
    return 3;
}
void init(char *v)
{
    trie *p=root;
    for(int i=0; v[i]; i++)
    {
        int tep=getid(v[i]);
        if(p->next[tep]==NULL)
        {
            p->next[tep]=new trie();
            node[triecont]=p->next[tep];
            p->next[tep]->id=triecont++;
        }
        p=p->next[tep];
    }
    p->mark++;
}
void getac()
{
    queue<trie*>q;
    q.push(root);
    while(!q.empty())
    {
        trie *p=q.front();
        q.pop();
        for(int i=0; i<4; i++)
        {
            if(p->next[i]==NULL)
            {
                if(p==root) p->next[i]=root;
                else p->next[i]=p->fail->next[i];
            }
            else
            {
                if(p==root) p->next[i]->fail=root;
                else p->next[i]->fail=p->fail->next[i];
                q.push(p->next[i]);
                if(p!=root) p->next[i]->mark+=p->next[i]->fail->mark;
            }
        }
    }
}
int dp[520][15000];
int main()
{
    int n,cas=1;
    while(scanf("%d",&n),n)
    {
        memset(node,0,sizeof(node));
        triecont=0;
        root=new trie();
        node[triecont]=root;
        root->id=triecont++;

        while(n--)
        {
            char x[123];
            scanf("%s",x);
            init(x);
        }
        getac();
        scanf("%s",fuck);
        int used[12],bit[12];
        memset(used,0,sizeof(used));
        memset(bit,0,sizeof(bit));
        for(int i=0; fuck[i]; i++)
        {
            used[getid(fuck[i])]++;
        }
        bit[0]=(used[3]+1)*(used[2]+1)*(used[1]+1);
        bit[1]=(used[3]+1)*(used[2]+1);
        bit[2]=(used[3]+1);
        bit[3]=1;
        memset(dp,-1,sizeof(dp));
        dp[0][0]=0;
        for(int A=0; A<=used[0]; A++)
        {
            for(int B=0; B<=used[1]; B++)
            {
                for(int C=0; C<=used[2]; C++)
                {
                    for(int D=0; D<=used[3]; D++)
                    {
                        int tep=A*bit[0]+B*bit[1]+C*bit[2]+D*bit[3];
                        for(int j=0; j<triecont; j++)
                        {
                            if(dp[j][tep]!=-1)
                            {
                                for(int k=0;k<4;k++)
                                {
                                    if(k==0 && used[0]==A) continue;
                                    if(k==1 && used[1]==B) continue;
                                    if(k==2 && used[2]==C) continue;
                                    if(k==3 && used[3]==D) continue;
                                    trie *p=node[j]->next[k];
                                    dp[p->id][tep+bit[k]]=max(dp[p->id][tep+bit[k]],dp[j][tep]+p->mark);
                                }
                            }
                        }
                    }
                }
            }
        }
        int ans=0;
        int lit=used[0]*bit[0]+used[1]*bit[1]+used[2]*bit[2]+used[3]*bit[3];
        for(int i=0;i<triecont;i++) ans=max(ans,dp[i][lit]);
        printf("Case %d: %d\n",cas++,ans);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GeoPandas是一个开源的Python库,旨在简化地理空间数据的处理和分析。它结合了Pandas和Shapely的能力,为Python用户提供了一个强大而灵活的工具来处理地理空间数据。以下是关于GeoPandas的详细介绍: 一、GeoPandas的基本概念 1. 定义 GeoPandas是建立在Pandas和Shapely之上的一个Python库,用于处理和分析地理空间数据。 它扩展了Pandas的DataFrame和Series数据结构,允许在其中存储和操作地理空间几何图形。 2. 核心数据结构 GeoDataFrame:GeoPandas的核心数据结构,是Pandas DataFrame的扩展。它包含一个或多个列,其中至少一列是几何列(geometry column),用于存储地理空间几何图形(如点、线、多边形等)。 GeoSeries:GeoPandas中的另一个重要数据结构,类似于Pandas的Series,但用于存储几何图形序列。 二、GeoPandas的功能特性 1. 读取和写入多种地理空间数据格式 GeoPandas支持读取和写入多种常见的地理空间数据格式,包括Shapefile、GeoJSON、PostGIS、KML等。这使得用户可以轻松地从各种数据源中加载地理空间数据,并将处理后的数据保存为所需的格式。 2. 地理空间几何图形的创建、编辑和分析 GeoPandas允许用户创建、编辑和分析地理空间几何图形,包括点、线、多边形等。它提供了丰富的空间操作函数,如缓冲区分析、交集、并集、差集等,使得用户可以方便地进行地理空间数据分析。 3. 数据可视化 GeoPandas内置了数据可视化功能,可以绘制地理空间数据的地图。用户可以使用matplotlib等库来进一步定制地图的样式和布局。 4. 空间连接和空间索引 GeoPandas支持空间连接操作,可以将两个GeoDataFrame按照空间关系(如相交、包含等)进行连接。此外,它还支持空间索引,可以提高地理空间数据查询的效率。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值