#1577 : 为了Hiho的荣耀
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
Hiho王国受到外敌入侵,为了Hiho的荣耀,国王决定组织骑兵反击。一个骑兵单位由一个兵和一匹马组成,其战斗力为1。单个的兵、单个的马或两个兵、两个马都不是骑兵单位,故没有战斗。
国王发现他的兵马排成了有序的 A、B两行,每一行中都既可能有兵,又可能有马。国王宣布了本次反击的出战策略:在A中随机选择连续的一段(至少一个),称为SubA,将这一段的兵马从左到右依次编号为0, 1, 2, 3 ...;同时将B中全部的兵马从左到右依次编号为0, 1, 2, 3 ... 。然后将SubA与B中编号相同的配对,一对兵马SubAi和Bi参战的条件是:∀ 0 ≤ j ≤ i,SubAj与Bj都可组成骑兵单位。
注意,前文中SubA的选择是随机的,是指其中的每一段不论其长度、位置,被选择的概率都相同。国王想知道这次出击的骑兵的战斗力之和的期望,你能帮帮他吗?
输入
第一行有两个数字n 、m,分别代表A、B的兵马数量。
第二行n个数字A0, A1, ...An-1,表示A中的兵马,其中Ai=0代表兵,Ai=1代表马,数字之间没有任何分隔符。
第三行m个数字B0, B1, ... Bm-1 ,表示B的兵马,Bi的形式和意义同上。
对于30%的数据, 1 ≤ n, m ≤ 50
对于50%的数据, 1 ≤ n, m ≤ 1000
对于100%的数据,1 ≤ n, m ≤ 1000000
输出
输出只有一行,包含一个小数,表示此次出击战斗力之和的期望。只要你的答案和标准答案相差不超过0.01就被视为是正确的。
样例输入
6 6
010101
101011
样例输出
1.57142857
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MX=1000000+1000;
int n,m;
char stra[MX],strb[MX];
int nex[MX];
void kmp_nex(char *s)
{
nex[0]=-1;
int k=-1,i=0;
int len=strlen(s);
while(s[i])
{
if(k==-1||s[i]==s[k])
{
k++;i++;
nex[i]=k;
}
else
{
k=nex[k];
}
}
}
ll KMP(char *ostr,char *mstr)
{
int i=0,j=0;
ll res=0;
kmp_nex(mstr);
while(ostr[i] )
{
if(j==-1 || ostr[i]==mstr[j])
{
++i;
++j;
if(mstr[j]==0)
{
res+=(ll)(j+1)*j/2+(ll)(n-i)*j;
j=nex[j];
}
}
else
{
res+=(ll)(j+1)*j/2+(ll)(n-i)*j;
j=nex[j];
}
}
return res;
}
int main()
{
while(cin>>n>>m)
{
scanf("%s%s",stra,strb);
stra[n]='#';stra[n+1]=0;
for(int i=0;i<m;i++)
{
if(strb[i]=='0') strb[i]='1';
else strb[i]='0';
}
ll res=KMP(stra,strb);
ll k=(ll)(n+1)*(ll)n/2;
printf("%.9lf\n",1.0*res/k);
}
return 0;
}