E - RLE
题意:
有一种字符串转换方式,例如
“aaabbcccc”“aaabbcccc”“aaabbcccc”可以转换为“a3b2c4”“a3b2c4”“a3b2c4”
求长度为nnn的字符串,有多少种不同的字符串可以使转换后的字符串长度小于nnn
思路:
动态规划
令f[i][j]f[i][j]f[i][j]为长度为iii的字符串,转换后的长度为jjj,有多少种情况
cal(x)cal(x)cal(x)表示连续xxx个相同的字母组成的字符串转换成新串后的长度
最最简单的dpdpdp转移办法即
f[i][j]=∑f[i−k][j−cal(k)]
f[i][j]=\sum f[i-k][j-cal(k)]
f[i][j]=∑f[i−k][j−cal(k)]
时间复杂度为O(n3)O(n^3)O(n3),无法通过本题
其实也不难发现
cal(1)=cal(2)=...=cal(9)=1cal(10)=cal(11)=...=cal(99)=2...
cal(1)=cal(2)=...=cal(9)=1\\cal(10)=cal(11)=...=cal(99)=2\\...
cal(1)=cal(2)=...=cal(9)=1cal(10)=cal(11)=...=cal(99)=2...
于是
f[i][j]=(f[i−1][j−1]+...+f[i−9][j−1])∗25f[i][j]=(f[i−10][j−2]+...+f[i−99][j−2])∗25...
f[i][j]=(f[i-1][j-1]+...+f[i-9][j-1])*25\\f[i][j]=(f[i-10][j-2]+...+f[i-99][j-2])*25\\...
f[i][j]=(f[i−1][j−1]+...+f[i−9][j−1])∗25f[i][j]=(f[i−10][j−2]+...+f[i−99][j−2])∗25...
注意特判开始的情况,字符串开始的连续区间有262626种
使用前缀和优化dpdpdp即可在O(n2)O(n^2)O(n2)的时间解决问题
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
ll f[3005][3005],sum[3005][3005];
ll cal(ll x)
{
if(x<10) return 2;
else if(x<100) return 3;
else if(x<1000) return 4;
else return 5;
}
ll n,mod;
int main()
{
scanf("%lld%lld",&n,&mod);
f[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(cal(i)==j)
{
f[i][j]+=26;f[i][j]%=mod;
}
if(j>2&&i>1)
{
int u=max(0,i-10);
f[i][j]+=((sum[i-1][j-2]-sum[u][j-2])%mod+mod)%mod*25;
f[i][j]%=mod;
}
if(j>3&&i>10)
{
int u=max(0,i-100);
f[i][j]+=((sum[i-10][j-3]-sum[u][j-3])%mod+mod)%mod*25;
f[i][j]%=mod;
}
if(j>4&&i>100)
{
int u=max(0,i-1000);
f[i][j]+=((sum[i-100][j-4]-sum[u][j-4])%mod+mod)%mod*25;
f[i][j]%=mod;
}
if(j>5&&i>1000)
{
int u=max(0,i-10000);
f[i][j]+=((sum[i-1000][j-5]-sum[u][j-5])%mod+mod)%mod*25;
f[i][j]%=mod;
}
sum[i][j]=sum[i-1][j]+f[i][j];
sum[i][j]%=mod;
}
}
ll ans=0;
for(int i=1;i<n;i++)
{
ans+=f[n][i];
ans%=mod;
}
printf("%lld\n",ans);
}
该博客讨论了一种字符串转换方式,通过E-RLE(Extended Run-Length Encoding)将重复字符进行压缩。博主提出了一种动态规划解决方案,通过计算不同长度和压缩长度的组合来找出所有可能的转换,并优化了时间复杂度从O(n^3)降低到O(n^2)。文章还提供了C++代码实现,并特别处理了起始字符的特判情况。
1269

被折叠的 条评论
为什么被折叠?



