链接:http://zhengruioi.com/problem/265
第一种操作使得你可以任意访问该字符串的全排列
因此可以得到(frac{n!}{a!*b!*c!*d!})种方案
然后把每一组(a,b,c,d)看成一个节点的话
第二种操作就是在这些节点中连边
最终答案就是一个最长路
tarjan缩点+dp即可
#include<bits/stdc++.h>
#define M 33
#define N 3300000
#define eps 1e-7
#define inf 1e9+7
#define db double
#define ll long long
#define ldb long double
#define ull unsigned long long
using namespace std;
inline ll read()
{
char ch=0;
ll x=0,flag=1;
while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
return x*flag;
}
struct node{ll a,b,c,d;}p[N];
struct edge{ll to,nxt;}e[N];
struct link{ll x,y;}lk[N];
ll num,head[N];
inline void add(ll x,ll y)
{
//if(x==y)return;
e[++num]={y,head[x]};head[x]=num;
}
char S[N],T[N];
ll n,m,size,w[N],v[N],C[M][M],id[M][M][M][M];
ll cal(ll a,ll b,ll c,ll d){return C[n][a]*C[n-a][b]*C[n-a-b][c];}
stack<ll>st;
bool in_stack[N];
ll times,bel_cnt,dp[N],dfn[N],low[N],bel[N];
void tarjan(ll x)
{
dfn[x]=low[x]=++times;
st.push(x);in_stack[x]=true;
for(ll i=head[x];i!=-1;i=e[i].nxt)
{
ll to=e[i].to;
if(!dfn[to])tarjan(to),low[x]=min(low[x],low[to]);
else if(in_stack[to])low[x]=min(low[x],dfn[to]);
}
if(dfn[x]==low[x])
{
ll t=x;
bel_cnt++;
do
{
t=st.top();st.pop();
in_stack[t]=false;
bel[t]=bel_cnt;v[bel_cnt]+=w[t];
}while(t!=x);
}
}
ll dfs(ll x)
{
if(dp[x]!=-1)return dp[x];
dp[x]=v[x];
for(ll i=head[x];i!=-1;i=e[i].nxt)
{
ll to=e[i].to;
dp[x]=max(dp[x],dfs(to)+v[x]);
}
return dp[x];
}
int main()
{
n=read();m=read();
num=-1;memset(head,-1,sizeof(head));
for(ll i=0;i<=n;i++)
{
C[i][0]=1;
for(ll j=1;j<=i;j++)C[i][j]=C[i-1][j-1]+C[i-1][j];
}
for(ll a=0;a<=n;a++)for(ll b=0;a+b<=n;b++)for(ll c=0;a+b+c<=n;c++)
{
ll d=n-a-b-c;
id[a][b][c][d]=++size;w[size]=cal(a,b,c,d);
}
for(ll i=1;i<=m;i++)
{
scanf("%s",S);scanf("%s",T);
ll len=max(strlen(S),strlen(T));
ll sa=0,sb=0,sc=0,sd=0,ta=0,tb=0,tc=0,td=0;
for(ll k=0;k<len;k++)
{
sa+=(S[k]=='A');
sb+=(S[k]=='B');
sc+=(S[k]=='C');
sd+=(S[k]=='D');
ta+=(T[k]=='A');
tb+=(T[k]=='B');
tc+=(T[k]=='C');
td+=(T[k]=='D');
}
for(ll a=sa;a<=n;a++)for(ll b=sb;a+b<=n;b++)for(ll c=sc;a+b+c<=n;c++)
{
ll d=n-a-b-c;
if(d<sd)continue;
add(id[a][b][c][d],id[a+ta-sa][b+tb-sb][c+tc-sc][d+td-sd]);
}
}
for(ll i=1;i<=size;i++)if(!dfn[i])tarjan(i);
ll cnt=0;
for(ll x=1;x<=size;x++)
for(ll i=head[x];i!=-1;i=e[i].nxt)
{
ll to=e[i].to;
if(bel[x]!=bel[to])lk[++cnt]=(link){bel[x],bel[to]};
}
num=-1;memset(head,-1,sizeof(head));
for(ll i=1;i<=cnt;i++)add(lk[i].x,lk[i].y);
ll ans=0;
memset(dp,-1,sizeof(dp));
for(ll i=1;i<=bel_cnt;i++)ans=max(ans,dfs(i));
printf("%lld",ans);
return 0;
}