每周题解:单词环

题目链接

单词环

题目描述

我们有 n n n 个字符串,每个字符串都是由 a ∼ z a∼z az 的小写英文字母组成的。

如果字符串 A A A 的结尾两个字符刚好与字符串 B B B 的开头两个字符相匹配,那么我们称 A A A B B B 能够相连(注意: A A A 能与 B B B 相连不代表 B B B 能与 A A A 相连)。

我们希望从给定的字符串中找出一些,使得它们首尾相连形成一个环串(一个串首尾相连也算),我们想要使这个环串的平均长度最大。

如下例:

ababc
bckjaca
caahoynaab

第一个串能与第二个串相连,第二个串能与第三个串相连,第三个串能与第一个串相连,我们按照此顺序相连,便形成了一个环串,长度为 5 + 7 + 10 = 22 5+7+10=22 5+7+10=22(重复部分算两次),总共使用了 3 3 3 个串,所以平均长度是 22 ÷ 3 ≈ 7.33 22÷3≈7.33 22÷37.33

输入格式

本题有多组数据。

每组数据的第一行,一个整数 n n n,表示字符串数量;

接下来 n n n 行,每行一个长度小于等于 1000 1000 1000 的字符串。

读入以 n = 0 n=0 n=0 结束。

输出格式

若不存在环串,输出No solution,否则输出最长的环串的平均长度,答案保留两位小数。

样例 #1

样例输入 #1

3
intercommunicational
alkylbenzenesulfonate
tetraiodophenolphthalein
0

样例输出 #1

21.66

提示

【数据范围】
1 ≤ n ≤ 1 0 5 1≤n≤10^5 1n105

算法思想

根据题目描述,要求是否存一个首尾相连的环串,如果存在的话,求最长的环串的平均长度。
不妨设环中每个字符串的长度为 W i W_i Wi,环中字符串的个数为 S S S,要求的是 ∑ W i S \frac{\sum W_i}{S} SWi的最大值。这种求“最优比率” 的问题,可以参考博主的另一个文章:每周算法:01分数规划。

建图

在图中最长的环串的平均长度首先考虑如何建图。一种直观的建图方式是将每个单词作为一个节点,如果这两个单词能够首尾匹配,则在这两个单词之间连接一条有向边,此时最多有 1 0 5 10^5 105个节点,在最坏情况下(字母都一样)要建 1 0 10 10^{10} 1010条边,显然不可行。

考虑一种等价的建图方式,将一个单词看作一条边:将开头两个字符和结尾两个字符作为节点,单词长度作为边权,连接一条边,如下图所示:
在这里插入图片描述
这样建图,节点数最多只有 26 × 26 = 676 26\times26=676 26×26=676个,边数即单词数= 1 0 5 10^5 105

01分数规划

本题求的是 ∑ W i S \frac{\sum W_i}{S} SWi的最大值,其中 ∑ W i \sum W_i Wi表示环串种单词长度之和, S S S表示单词个数。
最优比率问题(即01分数规划)可以用二分求解。即求是否存在 m i d mid mid使环串上各单词长度之和除以单词个数大于 m i d mid mid,即 ∑ W i S > m i d \frac{\sum W_i}{S}>mid SWi>mid,进一步整理可得: ∑ ( W i − m i d × 1 ) > 0 \sum (W_i-mid\times 1)>0 (Wimid×1)>0

那么,要判断在包含环的图中是否存在 m i d mid mid,使环串上各单词长度之和除以单词个数大于 m i d mid mid,就等价于判断当图中边权为 W i − m i d W_i-mid Wimid时,是否存在正权环。而判断是否存在正权环可以使用「SFPA」算法,基本思想与判断负环稍有不同。判断正权环时:

  • 要求最长路,即 d [ v ] < d [ u ] + w d[v] < d[u] + w d[v]<d[u]+w时,更新 v v v点到起点的最长路;
  • v v v点到起点的最长路被更新时,累加最长路中包含的边数,即 c n t [ v ] = c n t [ u ] + 1 cnt[v]=cnt[u]+1 cnt[v]=cnt[u]+1
  • 如果边数 c n t [ v ] > = n cnt[v]>=n cnt[v]>=n,说明图中存在正权环。

算法实现

综合上述,求 ∑ W i S \frac{\sum W_i}{S} SWi的最大值算法实现如下:

  • [ L , R ] [L,R] [L,R]范围内通过二分查找答案,对于中间结果 m i d mid mid
    • 使用SPFA算法判断当边权为 p i − m i d × w i p_i-mid\times w_i pimid×wi时,图中是否存在正权环
  • 如果存在正权环,则在 [ m i d , R ] [mid,R] [mid,R]范围继续查找答案
  • 否则不存在正权环,则在 [ L , m i d ] [L,mid] [L,mid]范围继续查找答案

最后,如何确定二分查找的范围:

  • 由于单词长度 W i > 0 W_i>0 Wi>0,那么 ∑ W i S > 0 \frac{\sum W_i}{S}>0 SWi>0;
  • 最多有 1 0 5 10^5 105个单词,每个单词的长度不超过 1000 1000 1000,因此 ∑ W i S ≤ 1000 \frac{\sum W_i}{S}\le1000 SWi1000

因此, ∑ W i S ∈ ( 0 , 1000 ] \frac{\sum W_i}{S}\in(0,1000] SWi(0,1000]

代码实现

#include <bits/stdc++.h>
using namespace std;
//有26*26个点
const int N = 700, M = 100005;
int n;
int h[N], e[M], w[M], ne[M], idx;
bool st[N];
double d[N];
void add(int a, int b, int c)  // 添加一条边a->b,边权为c
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
bool dfs(int u, double mid) //使用dfs实现SPFA,判断以u为起点是否存在正权环
{
    if(st[u]) return true; //走到访问过的点,存在环
    st[u] = true;
    bool flag = false;
    for(int i = h[u]; ~ i ; i = ne[i])
    {
        int  v = e[i];
        if(d[v] < d[u] + w[i] - mid)
        {
            d[v] = d[u] + w[i] - mid;
            flag = dfs(v, mid);
            if(flag) break;
        }
    }
    st[u] = false; //恢复现场
    return flag;
}
bool check(double mid)
{
    memset(d, 0, sizeof d);
    for(int i = 0; i < N; i ++) //枚举所有点作为起点,判读是否存在正权环
        if(dfs(i, mid)) return true;
    return false;
}
int main()
{
    string s;
    while(cin >> n, n)
    {
        idx = 0; //有多组测试样例
        memset(h, -1, sizeof h);
        for(int i = 0; i < n; i ++)
        {
            cin >> s;
            int c = s.size();
            if(c >= 2)
            {
                //将前两和后两个个字符转为26进制数
                int a = (s[0] - 'a') * 26 + s[1] - 'a';
                int b = (s[c - 2] - 'a') * 26 + s[c - 1] - 'a';
                add(a, b, c); //建一条a->b边权为c的边
                
            }
        }
        if(!check(0)) //当mid取0都不存在正权环时,说明无解
        { 
            puts("No solution"); continue;
        }
        double L = 0, R = 1000;
        while(R - L > 1e-4)
        {
            double mid = (L + R) / 2;
            if(check(mid)) L = mid;
            else R = mid;
        }
        printf("%.2lf\n", L);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/684521.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024-前端面试的正确打开方式(GitHub火爆场景题剖析)

写在前面 最近前端面试大家有没有感觉到场景题的压迫感&#xff01;&#xff01;&#xff01; 很显然普通面试八股不会怎么更新&#xff0c;而且就前端来说&#xff0c;面试并不是真正困难的&#xff0c;常规八股显示不出面试者的技术水平。 前端作为一个技术行业&#xff0c…

用于精准治疗和预防细菌感染的生物功能脂质纳米颗粒

引用信息 文 章&#xff1a;Biofunctional lipid nanoparticles for precision treatment and prophylaxis of bacterial infections. 期 刊&#xff1a;Science Advances&#xff08;影响因子&#xff1a;13.6&#xff09; 发表时间&#xff1a;2024年4月5日 作 者&a…

图片改大小的3个步骤,快速在线处理图片的方法

图片改大小是现在使用图片时经常要使用的一个功能&#xff0c;因为在很多的网上平台都会有对图片尺寸和图片大小的要求&#xff0c;只有符合平台要求的图片才可以正常上传使用。想要快速调整图片大小&#xff0c;可以在网上使用在线改图工具来处理&#xff0c;只需要简单的几步…

ViewModel原理分析

认识 ViewModel ViewModel 是一种用来存储和管理UI相关数据的类。 ViewModel 的作用可以从两个方面去理解&#xff1a; UI界面控制器&#xff1a;在最初的MVC模式中&#xff0c;由于 Activity / Fragment 承担的职责过重&#xff0c;因此在后续的 MVP、MVVM 模式中&#xff…

springboot项目部署需要redis集群问题

本来直接将redis为单独启动模式转为配置 yml文件 spring.redis.cluster.nodes: 192.168.12.78:8001,192.168.12.78:8002,192.168.12.78:8003, java文件 package io.sirc.config;import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.ann…

三、【源码】Mapper XML的解析和注册使用

源码地址&#xff1a;https://github.com/mybatis/mybatis-3/ 仓库地址&#xff1a;https://gitcode.net/qq_42665745/mybatis/-/tree/03-parse-mapperXML Mapper XML的解析和注册使用 流程&#xff1a; 1.Resources加载MyBatis配置文件生成Reader字符流 2.SqlSessionFact…

UnityXR Interactable Toolkit如何实现Climb爬梯子

前言 在VR中,通常会有一些交互需要我们做爬梯子,爬墙的操作,之前用VRTK3时,里面是还有这个Demo的,最近看XRI,发现也除了一个爬的示例,今天我们就来讲解一下 如何在Unity中使用XR Interaction Toolkit实现爬行(Climb)操作 环境配置 步骤 1:设置XR环境 确保你的Uni…

Linux学习总结

单行注释:# 多行注释::<<! ! cd # 进入家目录 cd ~ # 进入家目录 cd / # 进入根目录 cd - # 返回上一次目录 cd .. # 进入上一级目录 cd ../.. # 进入上上级目录 # 写法一 [命令] & # 写法二 nohup [命令] & 两种写法都可以…

商城项目【尚品汇】06压力测试-性能指标-Jmeter使用-压力测试报告

文章目录 1.压测目的2.性能指标3.Jmeter3.1Jmeter使用3.1.1 运行Jmeter3.1.2 添加线程组3.1.3设置HTTP请求3.1.4 设置监视器 3.2 查看Jmeter压测结果3.2.1 查看结果树3.2.2 查看汇总报告3.2.3 查看聚合报告3.2.4 查看汇总图 1.压测目的 内存泄漏&#xff1a;OOM&#xff0c;重…

Nginx配置详细解释

文章目录 一、配置详细解释关闭版本修改启动的进程数cpu与work进程绑定nginx进程的优先级work进程打开的文件个数event事件 二、Http设置协议配置说明mime虚拟主机aliaslocationaccess模块验证模块自定义错误页面自定义日志存放位置try_files检测文件是否存在长连接 一、配置详…

【vue-admin-template】设置前后端访问地址

最近在使用vue-admin-template模板进行二次开发&#xff0c;GitHub地址&#xff1a; Vue-Admin-Template。 如果要在该项目中设置前后端的访问IP及端口&#xff0c;可以这样做&#xff1a; 前端&#xff1a;在vue.config.js中&#xff1a; 后端&#xff1a;在request.js中&…

CorelDRAW 全称“CorelDRAW Graphics Suite

箭头在各种场景中被广泛使用。在设计中&#xff0c;设计师可以根据设计的目的和受众&#xff0c;巧妙地运用箭头来传达信息、创造视觉效果或引导观者的注意力。在CDR软件中可以为设计添加箭头&#xff0c;那具体该怎么做呢&#xff1f;下面由我带大家一起来了解CoreIDRAW箭头形…

【SpringBoot + Vue 尚庭公寓实战】项目介绍(一)

【尚庭公寓SpringBoot Vue 项目实战】项目介绍&#xff08;一&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】项目介绍&#xff08;一&#xff09;1、项目业务概述2、移动端介绍3、 后台管理系统4、 核心业务流程5、项目技术概述5、数据库设计 1、项目业务概述 …

青否数字人直播源码超级管理后台操作步骤!

青否数字人直播源码超级管理后台&#xff0c;我们将详细介绍一下数字人的管理后台的详细操作步骤&#xff01; 1.管理端入口 2.管理后台预览 账号管理&#xff0c;模特管理&#xff0c;声音管理&#xff0c;任务管理&#xff0c;卡类管理&#xff0c;代理商&#xff0c;克隆端 …

【WP|9】深入解析WordPress [add_shortcode]函数

add_shortcode 是 WordPress 中一个非常强大的函数&#xff0c;用于创建自定义的短代码&#xff08;shortcodes&#xff09;。短代码是一种简洁的方式&#xff0c;允许用户在内容中插入动态的、可重用的功能。通过 add_shortcode&#xff0c;开发者可以定义自己的短代码&#x…

xstream运用,JAVA对象转xml,xml转JAVA对象

目录 xstream 优点&#xff1a; 缺点&#xff1a; XStream的应用场景 用到的依赖 代码实现 xml标签对应的实体类 Header Package Request Response TradeInfo 工具类 XmlUtils 执行结果 xstream XStream是一个Java类库&#xff0c;主要用于将对象序列化为XML&#xf…

Cochrane Library循证医学数据库的介绍及文献下载

今天要讲的数据库是Cochrane Library循证医学数据库&#xff0c;我们先来了解一下该数据库&#xff1a; Cochrane Library是国际Cochrane Collaboration的主要产品&#xff0c;由英国Wiley InterScience公司出版发行。是一个提供高质量证据的数据库&#xff0c;是循证医学的证…

如何在centos中关闭swap分区

目录 前言 为什么要关闭 Swap 分区&#xff1f; 如何在 CentOS 中临时关闭 Swap 分区&#xff1f; 如何在 CentOS 中永久关闭 Swap 分区&#xff1f; 验证swap是否被关闭 潜在的风险和注意事项 总结 前言 Swap 分区是 Linux 系统中用于扩展物理内存的一种机制。在物理内存…

vs code 导出插件 导入到新电脑上

1. 在 现在的电脑上 导出插件 在vscode 上执行 code --list-extensions > extensions.txt 然后项目的目录就有了一个文件 2. 将他复制到新电脑上&#xff0c;把文件放在项目的最外层&#xff08;跟上面的目录一样&#xff09; 执行命令 Get-Content extensions.txt | ForE…

华硕NUC 14 Pro+ :科技与艺术相得益彰

什么样的迷你主机可以称之为“艺术品”&#xff1f;让我们一起认识NUC 14 Pro&#xff0c;看科技与艺术可以交汇出怎样的独特韵味&#xff1f; 科技与美学的邂逅 华硕NUC 14 Pro不仅是一台性能强劲的电脑主机&#xff0c;更像是一件可以在桌面“展出”的艺术品。精致小巧的体积…