首页 > 代码库 > EOJ 3261 分词
EOJ 3261 分词
字典树,$dp$。
记录$dp[i]$为以$i$为结尾获得的最大价值。枚举结尾一段是哪个单词,更新最大值。可以将字典中单词倒着建一棵字典树。
这题数据有点不严谨。
下面这组数据答案应该是负的。
3
a 0.1
aa 0.1
aaa 0.1
1
aaa
下面这组数据没通过的代码在$OJ$上也可以$AC$......
3
a 2
aa 2
aaa 2
1
aaab
正确答案是:
6.238325
aaa b
#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>using namespace std;double eps = 1e-7;struct X{ double f; int nx[26];}s[300010];int sz=0,root=0;int n,T;char t[5010];char tt[5010];double w;double dp[5010];int pre[5010];int r[5010];void Insert(){ int p = root; int len = strlen(t); for(int i=len-1 ; i>=0 ;i--) { if(t[i]>=‘A‘&&t[i]<=‘Z‘) t[i] = t[i] -‘A‘ + ‘a‘; if(s[p].nx[t[i]-‘a‘]==-1) s[p].nx[t[i]-‘a‘] = ++sz; p = s[p].nx[t[i]-‘a‘]; } s[p].f = w;}double get(int x){ if(x<0) return 0.0; return dp[x];}double work(double x){ if(x==0.0) return 0.0; return log(x);}int main(){ scanf("%d",&n); for(int i=0;i<=300005;i++) { s[i].f = 0; for(int j=0;j<=25;j++) s[i].nx[j] = -1; } sz=0; for(int i=1;i<=n;i++) { scanf("%s%lf",t,&w); Insert(); } scanf("%d",&T); while(T--) { scanf("%s",t); tt[0]=0; strcpy(tt,t); int len = strlen(t); for(int i=0;i<len;i++) { if(t[i]>=‘A‘&&t[i]<=‘Z‘) t[i] = t[i] - ‘A‘ +‘a‘; } memset(dp,0,sizeof dp); memset(pre,-1,sizeof pre); for(int i=0;i<len;i++) { int now = i, p = root; while(1) { if(now<0) break; if(s[p].nx[t[now]-‘a‘]==-1) { for(int e=0;e<now;e++) { if(dp[i] < dp[e]) { dp[i] = dp[e]; pre[i] = e; } } break; } p = s[p].nx[t[now]-‘a‘]; if(get(now-1) + work(s[p].f)*(i-now+1)*(i-now+1) > dp[i]) { dp[i] = get(now-1) + work(s[p].f)*(i-now+1)*(i-now+1); pre[i] = now-1; } now--; } } printf("%.6f\n",dp[len-1]); memset(r,0,sizeof r); int pp = pre[len-1]; while(1) { if(pp<0) break; r[pp]=1; pp = pre[pp]; } for(int i=0;i<len;i++) { printf("%c",tt[i]); if(r[i]) printf(" "); } printf("\n"); } return 0;}
EOJ 3261 分词
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。