EOJ 3261分词(静态字典树)@

来源:互联网 发布:async await python 编辑:程序博客网 时间:2024/06/05 03:30

分词

Time limit per test: 1.0 seconds

Time limit all tests: 1.0 seconds

Memory limit: 256 megabytes

有一句句子因为粘贴的时候出现了一点问题空格全部丢失了。现在给一本字典,每个词都对应这个词出现的频率(每十亿)。根据这个频率,我们可以根据下面的公式算出这个词带来的收益 P(word)

P(word)=len2(word)ln(frequency(word))

其中 frequency 就是上面所提到的频率。len 指的是单词的长度。

特别的,对于字典中没有出现过的词,P(word)=0

请对句子进行适当的分割,使得分割得到的所有词收益之和最大。同一个词可以重复出现,收益算作多次。

Input

先给出一本词典,词典的第一行是词条数(词条数约为 40 000),下面每行分别是单词和对应出现频率,用空格隔开。单词中只会出现英文字母大小写,不会有多余的空格。每个单词只会出现一次。频率是一个正实数

所有单词长度之和不超过 3105,最长单词长度不超过 30

接下来一行一个整数 T (T10),表示有 T 个查询。

下面 T 行,每行一个句子,句子长度不超过 5 000。句子中保证只含有英文字母大小写。注意单词匹配时,不区分大小写

词典数据来源于 Wikipedia Project Gutenberg(可能需要代理),其中 1-10000 词汇。

查询数据来源于 IELTS Test。

Output

对于每组数据,输出两行。

第一行是一个实数,表示最大能达到的收益。输出和答案相差不超过 103 即可认为正确。

第二行输出一连串单词,单词和单词之间用空格隔开。满足:

  • 把这些单词依次串联起来可以得到原句子;
  • 所有单词的收益值相加得到第一行的实数。

Examples

input
5ano 10ther 30another 10an 300other 201another
output
112.826670another
input
5ano 10.0ther 30.0another 10.0an 300.0other 2000.01another
output
212.837691an other

区间DP可能会超时;


#include<bits/stdc++.h>using namespace std;const int N =  3e5+10;double dp[N], val[N];int tre[N][30], a[N];char str[N];void dfs(int k){    if(!k) return ;    dfs(a[k]);    if(a[k]) printf(" ");    for(int i=a[k]+1;i<=k;i++) printf("%c",str[i]);    return ;}int main(){    int n;    while(scanf("%d", &n)!=EOF)    {        int cnt=0;//地址        val[0]=0;        memset(tre[0],0,sizeof(tre[0]));        for(int i=0; i<n; i++)        {            scanf("%s",str+1);            int len=strlen(str+1), k=0;            for(int j=1; j<=len; j++)            {                int x=str[j]>='a'?(str[j]-'a'):(str[j]-'A');                if(!tre[k][x])                {                    tre[k][x]=++cnt;                    memset(tre[cnt],0,sizeof(tre[cnt]));                    val[cnt]=0;                }                k=tre[k][x];            }            scanf("%lf",&val[k]);            val[k]=1.0*len*len*log(1.0*val[k]);        }        int  t;        scanf("%d", &t);        while(t--)        {            memset(dp,0,sizeof(dp));            scanf("%s",str+1);            int len=strlen(str+1);            memset(a,0,sizeof(a));            for(int i=1;i<=len;i++)            {                int k=0;                for(int j=0;j<35;j++)                {                    if(i+j>len) break;                    int x=str[i+j]>='a'?(str[i+j]-'a'):(str[i+j]-'A');                    if(tre[k][x])                    {                        k=tre[k][x];                        if(dp[i+j]<dp[i-1]+val[k])                        {                            dp[i+j]=dp[i-1]+val[k];                            a[i+j]=i-1;                        }                    }                    else break;                }            }            printf("%lf\n",dp[len]);            dfs(len);            printf("\n");        }    }    return 0;}

原创粉丝点击