CF205E-Little Elephant and Furik and Rubik

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 ( 1i|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 ( 1n2·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 106.

题解

E(n)=Pif(x,y)

Pi 表示每种字串 x,y 出现的可能

同时这个等式也可以表示成如下的形式:

E(n)=Pij=0lxj==yj

xj==yj 为1否则为0

l 为子串x的长度

然后转化为

E(n)=i=0lPi(xj==yj)

因为每种字串的出现的可能都是相等的

P1==P2==...Pn

所以

E(n)=Pj=0lxj==yj

我们可以看出本质上题目要求的就是所有子串中 xi==yi 的个数

与概率无关

那么我们可以枚举字符 c ,看能构造多少个子串xi==cyi==c

这里我们采用

比如说祖串 X:abav,Y:bacd ,对于 Y2 也就是 a 来说,我们可以匹配X1,因为 X1 为第一 X 第一个字符,所以无法向左扩展,向右可以扩展2个长度,我们还可以匹配X3,向左扩展1个长度,向右扩展1个长度,那么对于 a 来说,总共可以构造出的字串的个数为,13+22个。

但是我们发现这样还是没有办法解决问题,直接搜索匹配字符的复杂度为 O(N2) 的,对于 2105 的数据肯定超时,那么如何优化时间复杂度呢?

经过大仙的提醒我们可以观察到,对于 Yi ,对于在X串相同位置之前的匹配的字符 Xj 向左扩展的长度都是有 Xj 决定的即为j,向右扩展的长度都是由 Yi 决定的即为 i ,对于Yi之后的字符我们能够找到类似的性质,那么我们就可以预处理 j(Yj==Xi,j<=i) ,和 j(Yj==Xi,j>=i) ,然后通过 O(N) 的复杂度求解。

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值