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;
}
1002

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



