zoukankan      html  css  js  c++  java
  • 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
    ",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("
    ");
    
    	}
    
    	return 0;
    }
  • 相关阅读:
    ArcEngine开发——地图浏览
    C#中字符串与数值的相互转换
    ArcGIS数据编辑——反转线段方向
    数据库移植——从MySQL Server到MS SQL Server
    重新学习数据库范式
    使用动态链接库组件进行ArcGIS开发
    ArcGIS数据编辑——按比例拉伸要素的几何形状
    ArcGIS数据编辑——要素概括(简化)/平滑
    使用Paint事件重画GroupBox来修改边框颜色
    ArcEngine开发——从TocControl上获取鼠标点击位置的信息
  • 原文地址:https://www.cnblogs.com/zufezzt/p/6849695.html
Copyright © 2011-2022 走看看