zoukankan      html  css  js  c++  java
  • 2018.10.22-dtoi1554字符串函数(strfun)

    题目描述:

    两个等长的由大写英文字母构成的字符串a和b,从a中选择连续子串x,从b中选出连续子串y。子串x与子串y的长度相等。

    定义函数f(x,y)为满足条件xi=yi(1<=i<=|x|)的i的个数,计算f(x,y)的数学期望。

    输入:

    第一行输入n(1<=n<=2*10^5),表示a和b的长度

    第二行输入字符串a

    第三行输入字符串b

    输出:

       输出一个实数表示f(x,y)的期望,答案保留6位小数。  

    样例:

    题目为什么要给图片样例呢??!

    算法标签:期望dp

    思路:


    详细的在sgx神犇里有图文并茂的介绍: https://blog.csdn.net/qq_41717018/article/details/83217701

    这题总体还是很妙的,运用整体思想,我们考虑单个位置上有匹配会造成多少贡献,以下:

    当i<j时,我们发现,这个字母O,由于在B的开头一定在[j-i+1,j]中,可以找到会带来1的贡献的子串,由于B的结尾一定在[j,n]中,所以在A若在此位有贡献,则A的结尾一定在[i,i+n-j]中,所以总贡献即i*(n-j+1)。

    当i>j时,则类似i<j的分析,则贡献就是(n-i+1)*j。

    于是在一个子串中统计前缀出现的字母i出现的位置之和,和后缀字幕出现n-pos+1之和。

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define D double
    #define LL long long
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=2e5+5;char a[N],b[N];int n;LL f[30][N],g[30][N],sum;
    il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;}
    int main()
    {
        n=read();scanf(" %s",a+1);scanf(" %s",b+1);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=26;j++)f[j][i]=f[j][i-1];f[a[i]-'A'+1][i]+=(LL)i;
        }
        for(int i=n;i;i--){
            for(int j=1;j<=26;j++)g[j][i]=g[j][i+1];g[a[i]-'A'+1][i]+=1ll*(n-i+1);
        }
        for(int i=1;i<=n;i++)
            sum+=(LL)i*g[b[i]-'A'+1][i+1]+1ll*(n-i+1)*f[b[i]-'A'+1][i];
        printf("%.6lf
    ",(D)sum*6.0/(1.0*(1.0*(D)(n+1)*(D)(2*n+1)*(D)n)));
      return 0;
    }
    View Code
  • 相关阅读:
    C#=>递归反转栈
    C#=> 栈模仿堆的操作
    C# 栈=>随时读取栈中最小值
    vijos1574 摇钱树
    (二叉)堆
    分块大法好
    list
    动态规划——状压、树形
    区间动规平行四边形优化
    最长公共子序列(LCS)
  • 原文地址:https://www.cnblogs.com/Jessie-/p/9836012.html
Copyright © 2011-2022 走看看