CF205E-Little Elephant and Furik and Rubik
Description
Little Elephant loves Furik and Rubik, who he met in a small city Kremenchug.
The Little Elephant has two strings of equal length a and b, consisting only of uppercase English letters. The Little Elephant selects a pair of substrings of equal length — the first one from string a, the second one from string b. The choice is equiprobable among all possible pairs. Let’s denote the substring of a as x, and the substring of b — as y. The Little Elephant gives string x to Furik and string y — to Rubik.
Let’s assume that f(x, y) is the number of such positions of i ( 1 ≤ i ≤ |x| ), that xi = yi (where |x| is the length of lines x and y, and xi,yi are the i-th characters of strings x and y, correspondingly). Help Furik and Rubik find the expected value of f(x, y) .
Input
The first line contains a single integer n ( 1 ≤ n ≤ 2·105 ) — the length of strings a and b. The second line contains string a, the third line contains string b. The strings consist of uppercase English letters only. The length of both strings equals n .
Output
On a single line print a real number — the answer to the problem. The answer will be considered correct if its relative or absolute error does not exceed
10−6 .
题解
E(n)=∑Pi∗f(x,y)
Pi 表示每种字串 x,y 出现的可能
同时这个等式也可以表示成如下的形式:
E(n)=∑Pi∗∑j=0lxj==yj
xj==yj 为1否则为0
l
为子串
然后转化为
E(n)=∑∑i=0lPi∗(xj==yj)
因为每种字串的出现的可能都是相等的
即
P1==P2==...Pn
所以
E(n)=P∗∑∑j=0lxj==yj
我们可以看出本质上题目要求的就是所有子串中 xi==yi 的个数
与概率无关
那么我们可以枚举字符
c
,看能构造多少个子串
这里我们采用
比如说祖串
X:abav,Y:bacd
,对于
Y2
也就是
a
来说,我们可以匹配
但是我们发现这样还是没有办法解决问题,直接搜索匹配字符的复杂度为 O(N2) 的,对于 2∗105 的数据肯定超时,那么如何优化时间复杂度呢?
经过大仙的提醒我们可以观察到,对于
Yi
,对于在X串相同位置之前的匹配的字符
Xj
向左扩展的长度都是有
Xj
决定的即为j,向右扩展的长度都是由
Yi
决定的即为
i
,对于
PS:注意 Xi 不要算重复了
代码
/*********************************
Author: Toudsour
Created Time: 六 8/29 14:56:25 2015
File Name:CF205E.cpp
*********************************/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
char StrA[200100];
char StrB[200100];
long long CountP[26][200100];
long long CountE[26][200100];
int main()
{
int N;
scanf("%d",&N);
scanf("%s",&StrA[1]);
scanf("%s",&StrB[1]);
for(int i=1;i<=N;i++)
{
int A=StrA[i]-'A';
CountP[A][i]=i;
}
for(int i=N;i>=1;i--)
{
int A=StrA[i]-'A';
CountE[A][i]=N+1-i;
}
//for(int i=1;i<N;i++)
// cout<<CountP[0][i]<<" ";
//cout<<endl;
for(int i=1;i<=N;i++)
for(int j=0;j<26;j++)
CountP[j][i]+=CountP[j][i-1];
for(int i=N-1;i>=1;i--)
for(int j=0;j<26;j++)
CountE[j][i]+=CountE[j][i+1];
double Sum=0;
for(int i=1;i<=N;i++)
{
//cout<<i<<endl;
int A=StrB[i]-'A';
Sum+=CountP[A][i]*(N+1-i);
//cout<<(N-i+1)<<" "<<CountP[A][i]<<endl;
Sum+=CountE[A][i+1]*i;
//cout<<i<<" "<<CountE[A][i]<<endl;
}
double Ans=Sum;
double Temp=N;
Ans=Ans/(Temp*(Temp+1)*(2*Temp+1)/6);
printf("%.9f\n",Ans);
return 0;
}