容易发现有了交换相邻字符的操作后,只要字符串所含有的字符种类和数量相同其就是等价的。这样的状态只有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. China Cloud Computing Conference(2018.07.24)

    时间:2018.07.24地点:北京国家会议中心

  2. 2017-2018-4 20155203《网络对抗技术》Exp3 免杀原理与实践

    1.基础问题回答 (1)杀软是如何检测出恶意代码的? 分析恶意程序的行为特征,分析其代码流将其性质归类于恶意代码 (2)免杀是做什么? 使恶意代码避免被查杀,也就是要掩盖恶意代码的特征 (3)免杀的基 ...

  3. 20155304田宜楠《网络对抗技术》Exp1 PC平台逆向破解(5)M

    Exp1 PC平台逆向破解(5)M 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序 ...

  4. mfc CListBox

    通过ID操作对象 CListBox(列表框)控件 CListBox类常用成员 CListBox插入数据 CListBox删除数据 CListBox运用示例 一.CListBox类常用成员 CListB ...

  5. 我是SPI,我让框架更加优雅了!

    文章首发于[陈树义的博客],点击跳转到原文<我是 SPI,我让框架更加优雅了!> 自从上次小黑进入公司的架构组之后,小黑就承担起整个公司底层框架的开发工作.就在刚刚,小黑又接到一个任务:做 ...

  6. Android开发者不可或缺的四大工具

    Android开发者不可或缺的四大工具 android以其极强的开放性吸引着世界各地的开发者去开发各种各样的移动应用开发,而各种SDK更是为各个层次的开发者提供了一个可以尽情展示他们专业技能和创造性的 ...

  7. JNI探秘-----FileInputStream的read方法详解

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章我们已经分析过File ...

  8. 普通程序员看k8s的账户管理

    一.知识准备 ● 账户管理分为:userAccount与serviceAccount ● userAccount:通常是给人设计使用的,并且userAccount不在k8s集群内管理 ● servic ...

  9. PAT甲题题解-1078. Hashing (25)-hash散列

    二次方探测解决冲突一开始理解错了,难怪一直WA.先寻找key%TSize的index处,如果冲突,那么依此寻找(key+j*j)%TSize的位置,j=1~TSize-1如果都没有空位,则输出'-' ...

  10. 1093. Count PAT’s (25)-统计字符串中PAT出现的个数

    如题,统计PAT出现的个数,注意PAT不一定要相邻,看题目给的例子就知道了. num1代表目前为止P出现的个数,num12代表目前为止PA出现的个数,num123代表目前为止PAT出现的个数. 遇到P ...