第十五届蓝桥杯省赛第二场C/C++B组D题【前缀总分】题解(AC)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

暴力解法 O ( 26 n 5 ) O(26n^5) O(26n5)

枚举将第 i i i 个字符串的第 j j j 个字符改为 c c c 的所有方案,时间复杂度 O ( 26 n 2 ) O(26n^2) O(26n2),修改并计算总分, O ( n 3 ) O(n^3) O(n3)

暴力优化 O ( 26 n 3 log ⁡ n ) O(26n^3\log n) O(26n3logn)

我们可以使用字符串哈希来优化判断两个字符串是否相等。

另外,可以用二分来优化求两个字符串的最大前缀。

枚举所有方案的时间复杂度为 O ( 26 n 2 ) O(26n^2) O(26n2),处理修改以及计算总分的复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn)

再优化 O ( 26 n 3 ) O(26n^3) O(26n3)

首先,我们依旧使用上述暴力解法中的枚举方式——所有将第 i i i 个字符串的第 j j j 个字符改为 k k k,时间复杂度 O ( 26 n 2 ) O(26n^2) O(26n2)

接下来我们考虑,如果用不大于 O ( n ) O(n) O(n) 的时间去完成计算一个枚举的分数。

将第 i i i 个字符串的第 j j j 个字符改为 k k k 时,所影响答案的只有 P ( s 1 , s i ) , P ( s 2 , s i ) , P ( s 3 , s i ) , … , P ( s n , s i ) P(s_1, s_i), P(s_2, s_i), P(s_3, s_i), \dots, P(s_n, s_i) P(s1,si),P(s2,si),P(s3,si),,P(sn,si)

所以我们可以计算出未修改时的总得分的 t o t tot tot,计算出未修改时第 i i i 个字符串对答案的贡献 g [ i ] g[i] g[i]。设修改之后第 i i i 个字符串对答案的贡献为 r e s res res,那么修改之后的答案即为 t o t − g [ i ] + r e s tot - g[i] + res totg[i]+res

那么接下来,我们要尝试处理计算,将第 i i i 个字符串的第 j j j 个字符改为 k k k 之后,第 i i i 个字符串对答案的贡献。

那么显而易见,我们需要计算修改之后的第 i i i 字符串与剩下 n − 1 n-1 n1 个字符串的最大前缀。

设其中一个字符串为 s u s_u su,计算修改之后的 s i s_i si 与修改之前,只有第 j j j 个字符被改变, j j j 左侧的字符,以及右侧的字符均为改变。

那么我们可以尝试比较修改前的 s i s_i si s u s_u su 0 0 0 开始的最大前缀长度 l e f t left left

  • l e f t < j − 1 left < j - 1 left<j1,那么 s i s_i si s u s_u su 的最大前缀长度即为 l e f t left left
  • l e f t ≥ j − 1 left \geq j - 1 leftj1,那么说明 s i s_i si s u s_u su 的前 j − 1 j - 1 j1 个字符相等,此时我们需要判断修改之后的第 j j j 个字符是否相等:
    • 若第 j j j 个字符相等,则 s i s_i si s u s_u su 的最大前缀即为 l e f t + 1 + left + 1 + left+1+ s i s_i si s j s_j sj 的第 j + 1 j + 1 j+1 个字符开始的最大前缀)。
    • 若第 j j j 个字符不相等,则 s i s_i si s u s_u su 的最大前缀即为 l e f t left left

上述分析中,我们多次需要用到第 i i i 个字符串与第 j j j 个字符串从 k k k 开始的最大前缀。

考虑动态规划: f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k] 表示第 i i i 个字符串与第 j j j 个字符串从 k k k 开始的最大前缀长度。

考虑动态转移:

  • s [ i ] [ k ] = s [ j ] [ k ] s[i][k] = s[j][k] s[i][k]=s[j][k],则 f [ i ] [ j ] [ k ] = f [ i ] [ j ] [ k + 1 ] + 1 f[i][j][k] = f[i][j][k + 1] + 1 f[i][j][k]=f[i][j][k+1]+1
  • s [ i ] [ k ] ≠ s [ j ] [ k ] s[i][k] \neq s[j][k] s[i][k]=s[j][k],则 f [ i ] [ j ] [ k ] = 0 f[i][j][k] = 0 f[i][j][k]=0

由于计算 f [ i ] [ j ] [ k + 1 ] f[i][j][k + 1] f[i][j][k+1] 时,需要用到 f [ i ] [ j ] [ k + 1 ] f[i][j][k + 1] f[i][j][k+1],故预处理 f f f 数组时需要倒序处理。

暴力优化 O ( 26 n 3 log ⁡ n ) O(26n^3\log n) O(26n3logn)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;

const int N = 2e2 + 10, P = 131;

typedef unsigned long long ULL;

int n;
string str[N];
ULL f[N][N], p[N];
int g[N];
int tot;

ULL query(int u, int l, int r)
{
    return f[u][r] - f[u][l - 1] * p[r - l + 1];
}

int calc(int u, bool flag)
{
    int res = 0;
    for (int i = 1; i <= n; ++ i )
        if (i != u)
        {
            int l = 1, r = min(str[u].size() - 1, str[i].size() - 1);
            while (l < r)
            {
                int mid = l + r + 1 >> 1;
                if (query(i, 1, mid) == query(u, 1, mid))
                    l = mid;
                else
                    r = mid - 1;
            }
            if (query(i, 1, l) == query(u, 1, l))
                res += l;
        }
    
    if (flag)
    {
        g[u] = res;
        tot += res;
    }
    
    return res;
}

int modify(int u, int k, int c)
{
    char t = str[u][k];
    str[u][k] = 'a' + c;
    
    for (int i = 1; i < str[u].size(); ++ i )
        f[u][i] = f[u][i - 1] * P + str[u][i];

    int res = tot - g[u] * 2 + calc(u, false) * 2;
    
    str[u][k] = t;
    
    for (int i = 1; i < str[u].size(); ++ i )
        f[u][i] = f[u][i - 1] * P + str[u][i];
    
    return res / 2;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
    cin >> n;
    for (int i = 1; i <= n; ++ i )
    {
        cin >> str[i];
        str[i] = ' ' + str[i];
    }
    
    p[0] = 1;
    for (int i = 1; i < N; ++ i )
        p[i] = p[i - 1] * P;
    
    for (int i = 1; i <= n; ++ i )
        for (int j = 1; j < str[i].size(); ++ j )
            f[i][j] = f[i][j - 1] * P + str[i][j];
    
    for (int i = 1; i <= n; ++ i )
        calc(i, true);
    
    int res = 0;
    for (int i = 1; i <= n; ++ i )
        for (int j = 1; j < str[i].size(); ++ j )
            for (int k = 0; k < 26; ++ k )
                res = max(res, modify(i, j, k));
    
    cout << res << endl;
    
    return 0;
}

再优化 O ( 26 n 3 ) O(26n^3) O(26n3)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;

const int N = 2e2 + 10;

int n;
string str[N];
int g[N];
int tot;
int f[N][N][N];     //  [i, j, k] 第i个字符串和 第j个字符串 k个字符起最大连续数量

void init()
{
    for (int i = 1; i <= n; ++ i )
        for (int j = i + 1; j <= n; ++ j )
        {
            int mn = min(str[i].size(), str[j].size());
            for (int k = mn - 1; k >= 0; -- k )
                if (str[i][k] == str[j][k])
                    f[i][j][k] = f[j][i][k] = f[i][j][k + 1] + 1;
        }
    
    for (int i = 1; i <= n; ++ i )
    {
        for (int j = 1; j <= n; ++ j )
            g[i] += f[i][j][0];
        tot += g[i];
    }
    
    tot /= 2;
}

int modify(int u, int k, int c)
{
    int res = 0;
    for (int i = 1; i <= n; ++ i )
        if (i != u)
        {
            int left = min(f[u][i][0], k);
            res += left;
            
            if (left == k && str[i].size() > k && str[i][k] - 'a' == c)
            {
                res ++;
                res += f[u][i][k + 1];
            }
        }
    
    return tot - g[u] + res;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
    cin >> n;
    for (int i = 1; i <= n; ++ i )
        cin >> str[i];
    
    init();
    
    int res = 0;
    for (int i = 1; i <= n; ++ i )
        for (int j = 0; j < str[i].size(); ++ j )
            for (int k = 0; k < 26; ++ k )
                res = max(res, modify(i, j, k));
    
    cout << res << endl;
    
    return 0;
}

【在线测评】

在这里插入图片描述

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

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

相关文章

解析企业绩效通系统架构:构建高效管理与激励平台

在当今竞争激烈的商业环境中&#xff0c;企业需要不断提升管理效率和员工激励力度&#xff0c;以保持竞争优势并实现可持续发展。绩效通系统作为一种集成了绩效管理、激励机制和员工发展规划的管理工具&#xff0c;正逐渐成为现代企业管理的核心组成部分。本文将深入探讨企业绩…

mybatis-plus(二)集成与demo

一、集成 1、pom&#xff1a; 2、配置文件 3、启动类与业务逻辑&#xff1a; 无变化。引入mybatis-plus后&#xff0c;原mybatis逻辑可以正常使用。 二、demo 1、代码框架 &#xff08;1&#xff09;pom&#xff1a; <?xml version"1.0" encoding"UT…

Python实现本地视频/音频播放器

Python实现本地视频/音频播放器 在Python中&#xff0c;有几个库可以用于视频播放&#xff0c;但是没有一个库是完美的&#xff0c;因为它们可能依赖于外部软件或有一些限制。 先看介绍用Python实现本地视频播放器&#xff0c;再介绍用Python实现本地音乐播放器。 Python实现…

CSS Position定位(详解网页中的定位属性)

目录 一、Position介绍 1.概念 2.特点 3.作用 4.应用 二、Position用法 1.position属性 2.static定位 3.fixed定位 4.relative定位 5.absolute定位 6.sticky定位 7.重叠的元素 三、CSS定位属性 四、总结 一、Position介绍 1.概念 文档流&#xff08;Document Fl…

【从后端日志文件中过滤出sql语句】

从后端日志文件中过滤出sql语句 why?思路日志文件的格式 结果 why? 为什么会有这种需求&#xff1f;&#xff0c;mysql数据不小心被删了完全可以从备份数据恢复&#xff0c;或者从binlog中恢复&#xff0c;但是如果前面这两种方法没办法处理&#xff08;没有备份数据库文件、…

ray.tune调参学习笔记1:超参数优化器tuner设置

最近研究中学习使用python的ray.tune进行神经网络调参。在这里记录学习过程中的收获&#xff0c;希望能够帮助到有同样需求的人。学习过程主要参考ray官网文档&#xff0c;但由于笔者使用的ray为2.2.0版本&#xff0c;而官方文档为更高级版本&#xff0c;笔者代码和官方文档代码…

数字藏品:重塑艺术与科技的新媒介

数字藏品&#xff0c;这个新兴的词汇&#xff0c;正在逐渐渗透到我们的日常生活中。它不仅是一种新的艺术表达方式&#xff0c;更是一种科技与艺术相结合的全新媒介。那么&#xff0c;数字藏品究竟是什么呢&#xff1f; 首先&#xff0c;我们需要明确一点&#xff0c;数字藏品并…

qt QTreeWidget 学习

树形控件的节点可以有多层、多个子节点&#xff0c; 如果将子节点全部展开&#xff0c;那么每一行都是一个数据条目。QTreeWidgetItem 比较特殊&#xff0c;一个条目内部可以有多列数据信息&#xff0c;相当于表格控件一整行的表格单元集成为一个条目。 默认情况下&#xff0c;…

ELK技术介绍:背景、功能及应用场景全面解析

一、ELK概述 ELK是由Elasticsearch、Logstash和Kibana三个开源软件组成的日志管理解决方案&#xff0c;这一组合在近年来得到了广泛的关注和应用。ELK的出现&#xff0c;源于大数据和云计算技术的快速发展&#xff0c;以及对高效日志管理的迫切需求。 随着企业信息化程度…

Nginx 配置 SSL(HTTPS)详解

Nginx作为一款高性能的HTTP和反向代理服务器&#xff0c;自然支持SSL/TLS加密通信。本文将详细介绍如何在Nginx中配置SSL&#xff0c;实现HTTPS的访问。 随着互联网安全性的日益重要&#xff0c;HTTPS协议逐渐成为网站加密通信的标配。Nginx作为一款高性能的HTTP和反向代理服务…

6、ES单机设置用户名密码、集群设置用户名密码、es-head登录、如何去掉密码

目录 一、ES单节点密码配置1、修改配置文件2、 重启es服务3&#xff0c;执行修改密码命令4、访问服务 二、ES集群密码配置1、确定主节点2、生成elastic-stack-ca.p123、生成elastic-certificates.p124、修改配置文件并重启集群5、进行密码配置6、验证 三、es-head登录增加密码的…

ABAP json解析使用引用代替预定义数据结构

背景&#xff1a;在解析JSON数据时&#xff0c;通常会事先为定义相应的ABAP数据结构。但是&#xff0c;当遇到一些结构纵深较为复杂的情况时&#xff0c;会比较麻烦。 处理&#xff1a;使用引用类型来定义结构中的纵深部分来达到“省事”的目的&#xff0c;缺点在于访问时需要使…

Docker——开源的应用容器的引擎

目录 一、前言 1.虚拟化产品有哪些 1.1寄居架构 1.2源生架构 2.虚拟化产品对比/介绍 2.1虚拟化产品 2.1.1仿真虚拟化 2.1.2半虚拟化 2.1.3全虚拟化 2.2重点 2.2.1KVM——Linux内核来完成的功能和性能 2.2.2ESXI——用的比较多 二、Docker概述 1.Docker定义 2.Do…

赋能智慧校园!A3D数字孪生可视化,轻量又高效!

放假之后&#xff0c;学生们会逐步返学&#xff0c;大量人员出入校园&#xff0c;安全更是不容忽视&#xff0c;如何在短时间内对大批人员及设施进行智能监管&#xff1f;数字化转型是关键手段&#xff0c;我们可以融合线上线下数据&#xff0c;搭建3D立体的智慧校园&#xff0…

智能合约——提案demo

目录 这是一个超超超级简单的智能合约提案项目&#xff0c;你确定不点进来看一下吗&#xff1f; 引言&#xff1a; 1、搭建开发环境&#xff1a; 2、编写智能合约&#xff1a; 3、部署智能合约&#xff1a; ​编辑​编辑4、编写前端交互代码&#xff08;使用web3.js&…

MyBatis源码之MyBatis中SQL语句执行过程

MyBatis源码之MyBatis中SQL语句执行过程 SQL执行入口 我们在使用MyBatis编程时有两种方式&#xff1a; 方式一代码如下&#xff1a; SqlSession sqlSession sqlSessionFactory.openSession(); List<Student> studentList sqlSession.selectList("com.sjdwz.da…

C语言——自定义数据类型(结构体内存对齐)

C语言中不只有内置类型诸如 int 、float、char 等类型&#xff0c;还有自定义数据类型&#xff0c;本文主要探讨结构体&#xff08;struct&#xff09;、联合体&#xff08;union&#xff09;、枚举&#xff08;enum&#xff09;三种自定义数据类型。 在我之前的文章《C语言—…

WPF2 样式布局

样式布局 WPF中的各类控件元素, 都可以自由的设置其样式。 诸如: 字体(FontFamily) 字体大小(FontSize) 背景颜色(Background) 字体颜色(Foreground) 边距(Margin) 水平位置(HorizontalAlignment) 垂直位置(VerticalAlignment) 等等。 而样式则是组织和重用以上的重要工具。…

解码Linux中的Shell:一探脚本起源、发展与变量数据类型之奥秘

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、前言 1、Linux的起源与发展 2、什么是Shell脚本 3、Sh…

MySQL面试——聚簇/非聚簇索引

存储引擎是针对表结构&#xff0c;不是数据库 引擎层&#xff1a;对数据层以何种方式进行组织 update&#xff1a;加索引&#xff1a;行级锁&#xff1b;不加索引&#xff1a;表级锁