定义函数f(x,y)为满足条件xi=yi(1<=i<=|x|)的i的个数,计算f(x,y)的数学期望。(|x|=|y|)
首先显然不能每个串暴力,我们考虑单独计算每一个字符的贡献
对于b[i],若我们找到a[j]=b[i],可以分两种情况讨论
1.i<j 那么显然,对于b的字串,开头为[1,i],可以在a中找到完全对应的[j-i+1,j],而对于a的结尾则必然为[j,n],在b中可以找到[i,i+n-j]
所以贡献就是i*j
2.i>j 情况是对称的,所以贡献是(n-i+1)*(n-j+1)
所以对于a,我们维护一个前缀和sf[i][c]表示所有j满足j<=i而且a[j]=c的j的和,和一个后缀和sb[i][c]表示所有j满足j>=i且a[j]=c的就的和
那么对于b[i],贡献就是(n-i+1)*sf[i][b[i]]+i*sb[i+1][b[i]],累加即可,最后除以总方案数
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; char a[200010],b[200010]; double A=0; int n,sf[200010][26],sb[200010][26]; int main(){ scanf("%d%s%s",&n,a+1,b+1); for(int i=1;i<=n;++i){ memcpy(sf[i],sf[i-1],26<<2); sf[i][a[i]-'A']=sf[i-1][a[i]-'A']+i; } for(int i=n;i;--i){ memcpy(sb[i],sb[i+1],26<<2); sb[i][a[i]-'A']=sb[i+1][a[i]-'A']+(n-i+1); } for(long long i=1;i<=n;++i) A+=(n-i+1)*(sf[i][b[i]-'A'])+i*(sb[i+1][b[i]-'A']); //这里+1是为了防止重复计算 printf("%.6lf ",A*6/((n+1ll)*(n*2ll+1)*n)); }