文章目录

  • 一、题目
    • 1、题目描述
    • 2、基础框架
    • 3、原题链接
  • 二、解题报告
    • 1、思路分析
    • 2、时间复杂度
    • 3、代码详解
  • 三、本题小知识
  • 四、加群须知

一、题目

1、题目描述

  你需要从空字符串开始 构造 一个长度为 nnn 的字符串 sss ,构造的过程为每次给当前字符串 前面 添加 一个 字符。构造过程中得到的所有字符串编号为 111 到 nnn ,其中长度为 iii 的字符串编号为 sisisi 。比方说,s = "abaca" ,s1 == "a" ,s2 == "ca" ,s3 == "aca"依次类推。sisisi 的 得分 为 sisisi 和 snsnsn 的 最长公共前缀 的长度(注意 s == sn)。给你最终的字符串 sss ,请你返回每一个 sisisi 的 得分之和 。
  样例输入: s = "babab"
  样例输出: 9

2、基础框架

  • C语言 给出的基础框架代码如下:
long long sumScores(char * s){}

3、原题链接

LeetCode 6036. 构造字符串的总得分和

二、解题报告

1、思路分析

  (1)(1)(1) 要求 s[i]s[i]s[i] 和 s[n]s[n]s[n] 的最长公共前缀,假设原字符串为 SSS,对于 s[i]s[i]s[i] 表示的是:s[i]=S[n−i+1:n]s[i] = S[n-i+1: n]s[i]=S[n−i+1:n]
  (2)(2)(2) 那么问题就转变成了求 S[n−i+1:n]S[n-i+1: n]S[n−i+1:n] 和 S[1:n]S[1:n]S[1:n] 的最长公共前缀。
  (3)(3)(3) 首先我们需要回到一个概念,叫字符串哈希,具体可以参见如下:
    对于一个字符串 sss, s[l:r]s[l:r]s[l:r] 代表 sss 从 lll 到 rrr 的子串;
    hash(s[1:1])=(s[1]∗B0)modPhash(s[1:1]) = ( s[1]*B^{0} ) \mod Phash(s[1:1])=(s[1]∗B0)modP
    hash(s[1:2])=(s[1]∗B1+s[2]∗B0)modPhash(s[1:2]) = ( s[1]*B^{1} + s[2]*B^{0} ) \mod Phash(s[1:2])=(s[1]∗B1+s[2]∗B0)modP
    hash(s[1:3])=(s[1]∗B2+s[2]∗B1+s[3]∗B0)modPhash(s[1:3]) = ( s[1]*B^{2} + s[2]*B^{1} + s[3]*B^{0}) \mod Phash(s[1:3])=(s[1]∗B2+s[2]∗B1+s[3]∗B0)modP
    hash(s[1:4])=(s[1]∗B3+s[2]∗B2+s[3]∗B1+s[4]∗B0)modPhash(s[1:4]) = ( s[1]*B^{3} + s[2]*B^{2} + s[3]*B^{1} + s[4]*B^{0}) \mod Phash(s[1:4])=(s[1]∗B3+s[2]∗B2+s[3]∗B1+s[4]∗B0)modP
    hash(s[1:5])=(s[1]∗B4+s[2]∗B3+s[3]∗B2+s[4]∗B1+s[5]∗B0)modPhash(s[1:5]) = ( s[1]*B^{4} + s[2]*B^{3} + s[3]*B^{2} + s[4]*B^{1} + s[5]*B^{0}) \mod Phash(s[1:5])=(s[1]∗B4+s[2]∗B3+s[3]∗B2+s[4]∗B1+s[5]∗B0)modP
    那么我们如何求 hash(s[3:5])hash(s[3:5])hash(s[3:5]) 呢?
    直接对字符串遍历,得到的结果为 hash(s[3:5])=(s[3]∗B2+s[4]∗B1+s[5]∗B0)modPhash(s[3:5]) = ( s[3]*B^{2} + s[4]*B^{1} + s[5]*B^{0}) \mod Phash(s[3:5])=(s[3]∗B2+s[4]∗B1+s[5]∗B0)modP,那么通过如下减法,得到:
hash(s[1:5])−hash(s[3:5])=(s[1]∗B4+s[2]∗B3)modP=B3∗(s[1]∗B1+s[2]∗B0)modP=B3∗hash(s[1:2])modP\begin{aligned}hash(s[1:5]) - hash(s[3:5]) &= ( s[1]*B^{4} + s[2]*B^{3} ) \mod P \\ &= B^3 * ( s[1]*B^{1} + s[2]*B^{0} ) \mod P \\ &= B^3 * hash(s[1:2]) \mod P \end{aligned}hash(s[1:5])−hash(s[3:5])​=(s[1]∗B4+s[2]∗B3)modP=B3∗(s[1]∗B1+s[2]∗B0)modP=B3∗hash(s[1:2])modP​
    移项后整理式子,得到:
hash(s[3:5])=(hash(s[1:5])−B3∗hash(s[1:2]))modPhash(s[3:5]) = ( hash(s[1:5]) - B^3 * hash(s[1:2]) ) \mod Phash(s[3:5])=(hash(s[1:5])−B3∗hash(s[1:2]))modP
    那么对于更加一般的情况,令 h(r)=hash(s[1:r])h(r) = hash(s[1:r])h(r)=hash(s[1:r]),有:
hash(s[l:r])=(h(r)−Br−l+1∗h(l−1))modPhash(s[l:r]) = ( h(r) - B^{r-l+1} * h(l-1) ) \mod Phash(s[l:r])=(h(r)−Br−l+1∗h(l−1))modP
    其中 h(i)h(i)h(i) 和 BiB^iBi 都可以事先一次线性扫描预处理后放在数组中,则每次取子串哈希值的时间复杂度为 O(1)O(1)O(1)。
    对于字符串哈希更加深入的内容,可以参考:夜深人静写算法(九)- 哈希表。
  (4)(4)(4) 字符串哈希的模板如下:

#define ull unsigned long long
#define maxn 100010
#define P 10207
ull h[maxn], p[maxn];void initHash(const char *s) {// 这个字符串是从 1 - n-1int n = strlen(s);int i;p[0] = 1;h[0] = 0;for(i = 1; i < n; ++i) {h[i] = h[i-1] * P + s[i];p[i] = p[i-1] * P;}
}ull getSubHash(int l, int r) {return h[r] - h[l-1] * p[r - l + 1];
}

  (5)(5)(5) 于是,对于每个位置 iii,只要二分长度,然后通过字符串哈希求出最长的公共子串,累加长度就是答案了。

2、时间复杂度

   最坏时间复杂度 O(nlogn)O(nlogn)O(nlogn) 。

3、代码详解

#define ull unsigned long long
#define maxn 100010
#define P 10207
ull h[maxn], p[maxn];void initHash(const char *s) {// 这个字符串是从 1 - n-1int n = strlen(s);int i;p[0] = 1;h[0] = 0;for(i = 1; i < n; ++i) {h[i] = h[i-1] * P + s[i];p[i] = p[i-1] * P;}
}ull getSubHash(int l, int r) {return h[r] - h[l-1] * p[r - l + 1];
}class Solution {public:long long sumScores(string s) {s = "#" + s;long long ret = 0;int n = s.size() - 1;initHash(s.c_str());for(int i = 1; i <= n; ++i) {int l1 = n - i + 1;int l2 = 1;int l = 1, r = i;int ans = 0;while(l <= r) {int mid = (l + r) >> 1;if(getSubHash(l1, l1 + mid - 1) == getSubHash(l2, l2 + mid - 1)) {ans = mid;l = mid + 1;}else {r = mid - 1;}}ret += ans;}return ret;}
};

三、本题小知识

  字符串哈希的问题,可以解决很多比较难想的字符串问题(代替 KMP、后缀树组 等等)。


四、加群须知

  相信看我文章的大多数都是「 大学生 」,能上大学的都是「 精英 」,那么我们自然要「 精益求精 」,如果你还是「 大一 」,那么太好了,你拥有大把时间,当然你可以选择「 刷剧 」,然而,「 学好算法 」,三年后的你自然「 不能同日而语 」
  那么这里,我整理了「 几十个基础算法 」 的分类,点击开启:

LeetCode 6036. 构造字符串的总得分和相关推荐

  1. leetcode 1400. 构造 K 个回文字符串

    leetcode 1400. 构造 K 个回文字符串 文章目录 leetcode 1400. 构造 K 个回文字符串 一.题目 1.题目描述 2.基础框架 3.解题思路 一.题目 原题链接:1400. ...

  2. 代码随想录算法训练营第08天 | LeetCode 344.反转字符串,541. 反转字符串2,剑指Offer 05.替换空格,151.翻转字符串里的单词,剑指Offer58-II.左旋转字符串

    LeetCode [344. 反转字符串] 题目:编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 s 的形式给出. 不要给另外的数组分配额外的空间,你必须**原地修改输入数组**. ...

  3. LeetCode实战:字符串相乘

    题目英文 Given two non-negative integers num1 and num2 represented as strings, return the product of num ...

  4. LeetCode实战:字符串相加

    题目英文 Given two non-negative integers num1 and num2 represented as string, return the sum of num1 and ...

  5. leetcode——344. 反转字符串

    leetcode--344. 反转字符串 问题概述: 编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 char[] 的形式给出. 不要给另外的数组分配额外的空间,你必须原地修改输入 ...

  6. leetcode 344. 反转字符串 541. 反转字符串 II 双指针解

    目录 leetcode 344.反转字符串 1.题目 2.思考 leetcode 541. 反转字符串 II 1.题目 2.思考 leetcode 344.反转字符串 1.题目 2.思考 典型的双指针 ...

  7. 蓝桥杯练习题:对给定整数基于斐波拉契数列构造字符串

    文章目录 一.提出问题 二.解决问题 (一)分析 (二)编程 1.构造[1, n]范围内的斐波拉契数列表 2.基于斐波拉契数列构造字符串函数 3.编写主控程序 4.运行程序,查看结果 三.优化算法 一 ...

  8. C#版(击败97.76%的提交) - Leetcode 557. 反转字符串中的单词 III - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...

  9. LeetCode——1849. 将字符串拆分为递减的连续值(Splitting a String Into Descending Consecutive Val..)[中等]——分析及代码(Java)

    LeetCode--1849. 将字符串拆分为递减的连续值[Splitting a String Into Descending Consecutive Values][中等]--分析及代码[Java ...

最新文章

  1. Android自定义spinner下拉框实现的实现
  2. gradle_使用Gradle构建和应用AST转换
  3. 帆软报表(finereport) 复选框多值查询
  4. 字符串多模式精确匹配(脏字/敏感词汇搜索算法)——TTMP算法 之理论(转)...
  5. Qt中事件循环机制详解
  6. 在linux系统上使用jmeter
  7. Java里面的几种路径的区别
  8. 怎样用mysql查询测试_如何测试数据库查询优化器
  9. 日常生活开支记账明细_花钱如流水?拥有这两款记账APP,1年能省1万块!
  10. Android单元测试(五):依赖注入,将mock方便的用起来
  11. C语言随笔小算法:取出一个任意整数的每一位数值
  12. 计算机应用项目的主要领域,计算机应用基础_领域一.ppt
  13. JSBinding + SharpKit / JavaScript 加载流程
  14. Mysql --- 索引
  15. python to datetime_Python中缺少datetime.timedelta.to_seconds()-float?
  16. 嵌入式技术栈之I2S
  17. 【C++】1070:人口增长(信息学奥赛)
  18. 小程序html转wxml,微信小程序用wxParse解析html
  19. C#开发微信门户及应用(46)-基于Bootstrap的微信门户应用管理系统功能介绍
  20. 3种团队分组适应项目_对于新组建的团队,项目经理可以采用这5个破冰练习

热门文章

  1. 不小心删除了网络适配器中的无线网卡驱动?
  2. 详解色彩模型、色域以及颜色空间转换
  3. 记一次对易班前端解密的经过
  4. 【二十】 H.266/VVC | 仿射运动估计AMVP继承相邻块的运动信息函数 | addAffineMVPCandUnscaled函数
  5. 2022 世界人工智能大会,都讲了些啥?
  6. 解决问题(七)——jsf+spring+hibernate整合(一)
  7. QCA switch芯片配置说明
  8. cocos2dx layer理解
  9. Pytorch版本过高产生的RuntimeError: Legacy autograd function with non-static forward method is deprecated.
  10. echarts省级地图展示(包含3D地图)