容易发现有了交换相邻字符的操作后,只要字符串所含有的字符种类和数量相同其就是等价的。这样的状态只有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=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),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=,tmp[];
int dfn[N*N*N],low[N*N*N],stk[N*N*N],SET[N*N*N],top=,cnt=;
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<<];
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[]={};int n=;
biginteger tmp=(biginteger){x,y};
while (tmp.y) v[++n]=tmp.y%,tmp.y/=;
if (tmp.x)
{
n=;
while (tmp.x) v[++n]=tmp.x%,tmp.x/=;
}
for (int i=;i<=n;i++) v[i]=v[i]*a;
for (int i=;i<=n;i++)
v[i+]+=v[i]/,v[i]%=;
while (v[n+]) n++,v[n+]+=v[n]/,v[n]%=;
for (int i=;i>=;i--) tmp.y=tmp.y*+v[i];
for (int i=n;i>=;i--) tmp.x=tmp.x*+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+)*(n+)+y*(n+)+z+;}
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]=;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]]=;
top--;
}
SET[k]=t;ele[t].push_back(k);V[t]=V[t]+value[k];flag[k]=;top--;
}
}
namespace newgraph
{
int n,t=,p[N*N*N]={},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=,tail=;for (int i=;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>=;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,,sizeof(flag));
for (int i=;i<=t;i++)
{
for (int j=;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]=;
newgraph::addedge(i,SET[edge[k].to]);
newgraph::degree[SET[edge[k].to]]++;
}
for (int j=;j<ele[i].size();j++)
for (int k=p[ele[i][j]];k;k=edge[k].nxt)
flag[edge[k].to]=;
}
newgraph::n=t;
}
int main()
{
n=read(),m=read();
for (int i=;i<=m;i++)
{
scanf("%s",s+);scanf("%s",s2+);
a[i].n=strlen(s+);
for (int j=;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=;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+;
}
C[][]=;
for (int i=;i<=n;i++)
{
C[i][]=C[i][i]=;
for (int j=;j<i;j++)
C[i][j]=C[i-][j-]+C[i-][j];
}
for (int i=;i<=n;i++)
for (int j=;j<=n-i;j++)
for (int k=;k<=n-i-j;k++)
{
value[trans(i,j,k)]=(biginteger){,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=;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=;
for (int i=;i<=n;i++)
for (int j=;j<=n-i;j++)
for (int k=;k<=n-i-j;k++)
if (!dfn[trans(i,j,k)]) tarjan(trans(i,j,k));
rebuild();
newgraph::solve();
biginteger ans=(biginteger){,};
for (int i=;i<=t;i++) ans=max(ans,f[i]);
if (ans.x)
{
cout<<ans.x;
int x=;
while (ans.y) tmp[++x]=ans.y%,ans.y/=;
for (int i=;i>=;i--) cout<<tmp[i];
}
else cout<<ans.y;
return ;
}

#35 string(缩点+动态规划)的更多相关文章

  1. [NOI.AC#35]string 缩点+拓扑排序

    链接 因为有交换相邻字母,因此给你字符串就相当于给你了这个字符串的所有排列 把等价的串映射到整数范围,再根据 \(m\) 种魔法连边,缩点后在 DAG 上DP即可 无耻地用了int128 #inclu ...

  2. Codeforces #541 (Div2) - E. String Multiplication(动态规划)

    Problem   Codeforces #541 (Div2) - E. String Multiplication Time Limit: 2000 mSec Problem Descriptio ...

  3. BZOJ1179 [Apio2009]Atm Tarjan 强连通缩点 动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1179 题意概括 有一个有向图,每一个节点有一个权值,其中有一些结束点. 现在,你要从S出发,到达任 ...

  4. ACM学习历程—HDU2476 String painter(动态规划)

    http://acm.hdu.edu.cn/showproblem.php?pid=2476 题目大意是给定一个起始串和一个目标串,然后每次可以将某一段区间染成一种字符,问从起始串到目标串最少需要染多 ...

  5. Number String(HDU 4055,动态规划递推,前缀和优化)

    点击加号查看代码 #include<bits/stdc++.h>//前缀和优化版本,不易理解 using namespace std; #define ll long long ; ; l ...

  6. JS字符串格式化函数 string.format

    原生JS写的仿C#的字符串format函数,在此基础上又增加了便于JS使用的字面量对象参数. 参照C#中的规则,调用的时候会检测字符串格式,如果字符串格式不规范,或者传入的参数为null或undefi ...

  7. string.Format出现异常"输入的字符串格式有误"的解决方法

    string.Format出现异常"输入的字符串格式有误"的解决方法 今天在做项目时,碰到一个很奇怪的问题,我使用string.Format居然报“输入的字符串格式有误”的错误,我 ...

  8. python中string模块各属性以及函数的用法

    任何语言都离不开字符,那就会涉及对字符的操作,尤其是脚本语言更是频繁,不管是生产环境还是面试考验都要面对字符串的操作.     python的字符串操作通过2部分的方法函数基本上就可以解决所有的字符串 ...

  9. java String常见的处理

    import java.util.Arrays; class Demo5 { public static void main(String [] args) { String name1=" ...

随机推荐

  1. NYOJ 35 表达式求值

    一个模板了 哈哈. 这题由于已经包括了整形.浮点形了,以后也不须要特别处理了. /* 这里主要是逆波兰式的实现,使用两个stack 这里用字符串来模拟一个stack,第一步,将中缀表达式转变为后缀表达 ...

  2. Python3入门(十)——调试与测试

    一.异常处理 1.try...except...finally... 这个也就是Java里的try...cath..finally...了,直接看经典代码: try: print("开始执行 ...

  3. Android APK 签名比对(转)

    Android apk签名的过程 1. 生成MANIFEST.MF文件: 程序遍历update.apk包中的所有文件(entry),对非文件夹非签名文件的文件,逐个生成SHA1的数字签名信息,再用Ba ...

  4. Nuget包CommonServiceLocator从1.0.3升级到2.0.4时MvvmLight的ViewModelLocator初始化SimpleIoc.Default格式不匹配问题

    原文:Nuget包CommonServiceLocator从1.0.3升级到2.0.4时MvvmLight的ViewModelLocator初始化SimpleIoc.Default格式不匹配问题 把旧 ...

  5. 升级webpack2

    更新:webpack3已经出来了,官方说从2到升级到3不用改一行配置,98%的人没有错误. 项目中用的是webpack1.webpack2已经出来一段时间了.决定升级.其实改动不是很大.修改加测试共花 ...

  6. github协同开发

    看官请移步GitHub团队项目合作流程 本文是上述链接的截图,担心哪天作者不小心删除了,备一份在自己这里,仅为自己看着方便.侵权请告知

  7. 分布式Redis缓存串讲(一)

    互联网应用的基石 现在流量稍微大些的网站,都会采取Redis.基于Redis的内存缓存特性,可以大幅度降低数据库的访问量,大大提升了网站的并发能力,充当数据库的削量先锋.既然Redis这么重要,我们从 ...

  8. 《Effective Java》学习笔记 —— 枚举、注解与方法

    Java的枚举.注解与方法... 第30条 用枚举代替int常量 第31条 用实例域代替序数 可以考虑定义一个final int 代替枚举中的 ordinal() 方法. 第32条 用EnumSet代 ...

  9. Nginx浅析

    Nginx浅析 Nginx是什么 总的来说,Nginx其实就是一个和apache类似的服务器软件. Nginx是一款轻量级的Web服务器/反向代理服务器以及电子邮件代理服务器,并在一个BSD-like ...

  10. 用10分钟,搭建图像处理编程环境,0失败!(python语言,windows系统)

    以前,你可能看过很多的文章,开始搭建一个图像处理的编程环境. 结果,按照教程一步一步做的时候,总是出现各种各样的问题. 就算成功了,后续开发过程中要用到不同版本的opencv,不同版本python,更 ...