JZOJ5167. 【NOIP2017模拟6.26】下蛋爷

来源:互联网 发布:linux初级运维招聘 编辑:程序博客网 时间:2024/04/28 07:56

这里写图片描述

分析

通过观察,我们可以发现,对于出现次数相同的单词,遗忘的概率都相同。
所以,我们只需要求出相应出现次数的概率即可。

fi表示出现次数为i的遗忘概率。
那么fi 就应该等于fi1 (因为i-1的没有忘记,i就不是出现次数最少的)再加上i-1在这一次中忘记的概率。
这个概率是Ci1k(1p)i1pki+1

对于每一个单词在文章的出现次数,就可以通过ac自动机算出来。

code

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define N 203#define db doubleusing namespace std;struct arr{    int x,y;}a[N];struct node{    int son[26];    int num,fail,up;}tr[N*N],now;int q[N*N];int n,m,k,x,tot;db p,sum,ans[N],g[N],mi[N];char s[10000003],t[N][23],ch;int next[21],len[N];void build(int i){    int x=1;    for(int y=1;y<=len[i];y++)    {           if(!tr[x].son[t[i][y]-97])tr[x].son[t[i][y]-97]=++tot;        x=tr[x].son[t[i][y]-97];    }    tr[x].num=i;}void buildfail(){    int i=0,j=1;    q[1]=1;    while(i<j)    {        now=tr[q[++i]];        for(int k=0;k<=25;k++)            if(now.son[k])            {                q[++j]=now.son[k];                int x=q[j],z=now.fail;                while(z && !tr[z].son[k])z=tr[z].fail;                tr[x].fail=tr[z].son[k];                tr[x].fail=max(tr[x].fail,1);                if(tr[tr[x].fail].num)tr[x].up=tr[x].fail;else tr[x].up=tr[tr[x].fail].up;            }    }}void ac_automation(){    int x=1;    for(int i=1;i<=len[0];i++)    {        int in=s[i]-'a';        while(x!=1 && !tr[x].son[in]) x=tr[x].fail;        x=tr[x].son[in];        if(!x)x=1;        int q=x;        while(q>1)        {            a[tr[q].num].x++;            q=tr[q].up;        }    }}bool cmp(arr a,arr b){    return a.x<b.x;}void make(int x){    memset(next,0,sizeof(next));    int j=0;    for(int i=2;i<=len[x];i++)    {        while(j>0 && t[x][j+1]!=t[x][i])j=next[j];        if(t[x][i]==t[x][j+1])j++;        next[i]=j;    }}int kmp(int x){    int j=0,sum=0;    for(int i=1;i<=len[0];i++)    {        while(j>0 && s[i]!=t[x][j+1])j=next[j];        if(s[i]==t[x][j+1])j++;        if(j==len[x])        {            sum++;            j=next[len[x]];        }    }    return sum;}db C(int n,int m){    db ans=1.0;    for(int i=n;i;i--)        ans=ans*(m-i+1)*1.0/i;    return ans;}void read(int i){    ch=getchar();    while(ch<'a' || ch>'z')ch=getchar();    while('a'<=ch && ch<='z')t[i][++len[i]]=ch,ch=getchar();}int main(){    scanf("%d",&n);    tot=1;    for(int i=1;i<=n;i++)        read(i),build(i),a[i].y=i;    //scanf("%s",t[i]+1),len[i]=strlen(t[i]+1);    //scanf("%s",ss+1);    //for(int i=1;i<=strlen(ss+1);i++)    ch=getchar();    while(ch<'a' || ch>'z')ch=getchar();    while(ch!='\n' && ch !='\r')    {        if('a'<=ch && ch<='z')s[++len[0]]=ch;else        if('A'<=ch && ch<='Z')s[++len[0]]=ch+32;        ch=getchar();    }    scanf("%lf%d",&p,&k);    /*for(int i=1;i<=n;i++)        make(i),a[i].x=kmp(i),a[i].y=i;*/    buildfail();/*  for(int i=1;i<=tot;i++)        printf("%d ",tr[i].fail);*/    ac_automation();    sort(a+1,a+1+n,cmp);    a[0].x=-123;    m=0;    for(int i=1;i<=n;i++)        if(a[i].x!=a[i-1].x)m++;    sum=1;    mi[0]=1;    for(int i=1;i<=k;i++)        mi[i]=mi[i-1]*p;    for(int i=1;i<=m;i++)    {        ans[i]=ans[i-1]+C(i-1,k)*sum*mi[k-i+1];        sum*=1-p;    }    x=0;    for(int i=1;i<=n;i++)    {        if(a[i].x!=a[i-1].x)x++;        g[a[i].y]=ans[x];    }    for(int i=1;i<=n;i++)        printf("%.3lf ",g[i]);}
原创粉丝点击