zoukankan      html  css  js  c++  java
  • #35 string(缩点+动态规划)

      容易发现有了交换相邻字符的操作后,只要字符串所含有的字符种类和数量相同其就是等价的。这样的状态只有n^3级别,将其抽象成点子串变换抽象成边后就是求最长路径了,缩点dp解决。

      码量巨大,不是很明白要怎样才能用3k写完。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 55
    #define P 100000000000000000LL
    unsigned long long C[N][N];
    int n,m,p[N*N*N],t=0,tmp[20];
    int dfn[N*N*N],low[N*N*N],stk[N*N*N],SET[N*N*N],top=0,cnt=0;
    bool flag[N*N*N];
    char s[N],s2[N];
    vector<int> ele[N*N*N];
    struct magic{int n,a,b,c,x,y,z;}a[N<<1];
    struct data{int to,nxt;}edge[N*N*N*N];
    struct biginteger
    {
        unsigned long long x,y;
        bool operator <(const biginteger&a) const
        {
            return x==a.x?y<a.y:x<a.x;
        }
        bool operator >(const biginteger&a) const
        {
            return x==a.x?y>a.y:x>a.x;
        }
        biginteger operator +(const biginteger&a) const
        {
            biginteger v=(biginteger){x,y};
            v.x+=a.x;v.y+=a.y;
            if (v.y>=P) v.x++,v.y-=P;
            return v;
        }
        biginteger operator *(const unsigned long long&a) const
        {
            unsigned long long v[40]={0};int n=0;
            biginteger tmp=(biginteger){x,y};
            while (tmp.y) v[++n]=tmp.y%10,tmp.y/=10;    
            if (tmp.x)
            {
                n=17;
                while (tmp.x) v[++n]=tmp.x%10,tmp.x/=10;
            }
            for (int i=1;i<=n;i++) v[i]=v[i]*a;
            for (int i=1;i<=n;i++)
            v[i+1]+=v[i]/10,v[i]%=10;
            while (v[n+1]) n++,v[n+1]+=v[n]/10,v[n]%=10;
            for (int i=17;i>=1;i--) tmp.y=tmp.y*10+v[i];
            for (int i=n;i>=18;i--) tmp.x=tmp.x*10+v[i];
            return tmp;
        }
    }value[N*N*N],V[N*N*N],f[N*N*N];
    int trans(int x,int y,int z){return x*(n+1)*(n+1)+y*(n+1)+z+1;}
    void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
    void tarjan(int k)
    {
        dfn[k]=low[k]=++cnt;
        flag[k]=1;stk[++top]=k;
        for (int i=p[k];i;i=edge[i].nxt)
        if (!dfn[edge[i].to]) tarjan(edge[i].to),low[k]=min(low[k],low[edge[i].to]);
        else if (flag[edge[i].to]) low[k]=min(low[k],dfn[edge[i].to]);
        if (dfn[k]==low[k])
        {
            t++;
            while (stk[top]!=k)
            {
                SET[stk[top]]=t;
                ele[t].push_back(stk[top]);
                V[t]=V[t]+value[stk[top]];
                flag[stk[top]]=0;
                top--;
            }
            SET[k]=t;ele[t].push_back(k);V[t]=V[t]+value[k];flag[k]=0;top--;
        }
    }
    namespace newgraph
    {
        int n,t=0,p[N*N*N]={0},degree[N*N*N],q[N*N*N];
        struct data{int to,nxt;}edge[N*N*N*N];
        void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
        void topsort()
        {
            int head=0,tail=0;for (int i=1;i<=n;i++) if (!degree[i]) q[++tail]=i;
            while (tail<n)
            {
                int x=q[++head];
                for (int i=p[x];i;i=edge[i].nxt)
                {
                    degree[edge[i].to]--;
                    if (!degree[edge[i].to]) q[++tail]=edge[i].to;
                }
            }
        }
        void solve()
        {
            topsort();
            for (int i=n;i>=1;i--)
            {
                for (int j=p[q[i]];j;j=edge[j].nxt)
                f[q[i]]=max(f[q[i]],f[edge[j].to]);
                f[q[i]]=f[q[i]]+V[q[i]];
            }
        }
    }
    void rebuild()
    {
        memset(flag,0,sizeof(flag));
        for (int i=1;i<=t;i++)
        {
            for (int j=0;j<ele[i].size();j++)
                for (int k=p[ele[i][j]];k;k=edge[k].nxt)
                if (!flag[edge[k].to]&&SET[edge[k].to]!=i)
                {
                    flag[edge[k].to]=1;
                    newgraph::addedge(i,SET[edge[k].to]);
                    newgraph::degree[SET[edge[k].to]]++;
                }
            for (int j=0;j<ele[i].size();j++)
                for (int k=p[ele[i][j]];k;k=edge[k].nxt)
                flag[edge[k].to]=0;
        }
        newgraph::n=t;
    }
    int main()
    {
        n=read(),m=read();
        for (int i=1;i<=m;i++)
        {
            scanf("%s",s+1);scanf("%s",s2+1);
            a[i].n=strlen(s+1);
            for (int j=1;j<=a[i].n;j++)
            if (s[j]=='A') a[i].a++;
            else if (s[j]=='B') a[i].b++;
            else if (s[j]=='C') a[i].c++;
            for (int j=1;j<=a[i].n;j++)
            if (s2[j]=='A') a[i].x++;
            else if (s2[j]=='B') a[i].y++;
            else if (s2[j]=='C') a[i].z++;
            if (a[i].a==a[i].x&&a[i].b==a[i].y&&a[i].c==a[i].z) a[i].a=a[i].b=a[i].c=n+1;
        }
        C[0][0]=1;
        for (int i=1;i<=n;i++)
        {
            C[i][0]=C[i][i]=1;
            for (int j=1;j<i;j++)
            C[i][j]=C[i-1][j-1]+C[i-1][j];
        }
        for (int i=0;i<=n;i++)
            for (int j=0;j<=n-i;j++)
                for (int k=0;k<=n-i-j;k++)
                {
                    value[trans(i,j,k)]=(biginteger){0,C[n][i]};
                    value[trans(i,j,k)]=value[trans(i,j,k)]*C[n-i][j];
                    value[trans(i,j,k)]=value[trans(i,j,k)]*C[n-i-j][k];
                    for (int x=1;x<=m;x++)
                    if (i>=a[x].a&&j>=a[x].b&&k>=a[x].c&&n-i-j-k>=a[x].n-a[x].a-a[x].b-a[x].c)
                    addedge(trans(i,j,k),trans(i-a[x].a+a[x].x,j-a[x].b+a[x].y,k-a[x].c+a[x].z));
                }
        t=0;
        for (int i=0;i<=n;i++)
            for (int j=0;j<=n-i;j++)
                for (int k=0;k<=n-i-j;k++)
                if (!dfn[trans(i,j,k)]) tarjan(trans(i,j,k));
        rebuild();
        newgraph::solve();
        biginteger ans=(biginteger){0,0};
        for (int i=1;i<=t;i++) ans=max(ans,f[i]);
        if (ans.x)
        {
            cout<<ans.x;
            int x=0;
            while (ans.y) tmp[++x]=ans.y%10,ans.y/=10;
            for (int i=17;i>=1;i--) cout<<tmp[i];
        }
        else cout<<ans.y;
        return 0;
    }
  • 相关阅读:
    《RocketMQ源码系列》心跳机制
    《RocketMQ源码系列》broker是如何注册到nameserver的
    使用redis客户端工具RedisClient连接windows和linux下的redis并解决无法连接redis的问题
    windows下安装Linux
    redis客户端工具RedisClient的使用
    redis哨兵机制配置
    redis数据的两种持久化方式rdb和aof对比(二)
    redis数据的两种持久化方式rdb和aof对比(一)
    windows下的redis主从复制
    redis持久化配置:rdb和aof
  • 原文地址:https://www.cnblogs.com/Gloid/p/9613467.html
Copyright © 2011-2022 走看看