hdu 3341 Lost's revenge(AC自动机+DP)

题意:给出n个串,再给出一个串A,现在可以随便改变A串中字符的顺序,问重排后n个串最多与A有多少匹配。

思路:构建AC自动机以后,用dp[i][j][k]表示长度为i的串在AC自动机的j结点,状态为k时的最大匹配数,这里k是ACGT字符个数的一个状态,我用了一个四维数组来把这个状态映射为一个数,用这个数来表示状态,这样就比较好写了。。。状态方程也比较简单……


代码:


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=500+10;
const int maxm=10000+10;
int ch[maxn][4],next[maxn],lastv[maxn],val[maxn],size;
void Init()
{
    memset(ch[0],0,sizeof(ch[0]));
    memset(next,0,sizeof(next));
    memset(lastv,0,sizeof(lastv));
    size=val[0]=0;
}
int indx(char c)
{
    if(c=='A') return 0;
    if(c=='C') return 1;
    if(c=='G') return 2;
    return 3;
}
void Insert(const char *s)
{
    int u=0,n=strlen(s);
    for(int i=0;iq;
    for(int c=0;c<4;++c)
        if(ch[0][c]) q.push(ch[0][c]);
    int r,u,v;
    while(!q.empty())
    {
        r=q.front();q.pop();
        for(int c=0;c<4;++c)
        {
            u=ch[r][c];
            if(!u) {ch[r][c]=ch[next[r]][c];continue;}
            q.push(u);
            v=next[r];
            while(v&&!ch[v][c]) v=next[v];
            next[u]=ch[v][c];
            lastv[u]=val[next[u]]?next[u]:lastv[next[u]];
        }
    }
}
char str[55];
int dp[2][maxn][maxm],st[2][maxm][4];
int id[41][41][41][41],tot1,tot2;
int counts[maxn],tmp[4];
int solve()
{
    int n=strlen(str);
    memset(dp,0xff,sizeof(dp));
    memset(st,0,sizeof(st));
    memset(id,0,sizeof(id));
    memset(tmp,0,sizeof(tmp));
    memset(counts,0,sizeof(counts));
    tot1=tot2=0;
    int u;
    for(int i=0;i<=size;++i)
    {
        if(val[i]||lastv[i])
        {
            u=val[i]?i:lastv[i];
            while(u)
            {
                counts[i]+=val[u];
                u=lastv[u];
            }
        }
    }
    for(int i=0;i

你可能感兴趣的:(字符串)