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;
}
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值