当前位置:网站首页>leetcode 2223 — 构造字符串的总得分和
leetcode 2223 — 构造字符串的总得分和
2022-04-23 21:59:00 【coding-hwz】
一、题目描述

二、算法
这道题实际上就是考察的Z 算法。
1、泛化问题描述
对于个长度为 n n n 的字符串 s s s。定义函数 z [ i ] z[i] z[i] 表示 s s s 和 s [ i : n − 1 ] s[i:n-1] s[i:n−1] 的最长公共前缀的长度。 给出计算
z z z 的算法。 注:这里 s [ i : n − 1 ] s[i:n-1] s[i:n−1] 包含 s [ i ] s[i] s[i] 和 s [ n − 1 ] s[n-1] s[n−1]。
2、分析
与 KMP 类似,计算 z [ i ] z[i] z[i] 时需要用到前面计算过程的经验。这个算法的核心在于:维护了 [ l , r ] [l, r] [l,r] 区间,满足 r = max 0 ≤ k < i k + z [ k ] − 1 (1) r = \max \limits_{0 \le k < i}k+z[k]-1\tag{1} r=0≤k<imaxk+z[k]−1(1) l + z [ l ] − 1 = r (2) l+z[l]-1=r\tag{2} l+z[l]−1=r(2)
不难发现, [ l , r ] [l, r] [l,r] 实际上是 s s s 和 s [ l : n − 1 ] s[l:n-1] s[l:n−1] 的最长公共前缀区间。因此,我们可以得到 s [ 0 : r − l ] = s [ l : r ] (3) s[0:r-l]=s[l:r]\tag{3} s[0:r−l]=s[l:r](3)
当我们需要计算 z [ i ] z[i] z[i] 时,需要分情况讨论:
(1)如果 i ≤ r i\le r i≤r,对 (3) 式的左右两端的起始区间同时加上 i − l i-l i−l 可以得到 s [ i − l : r − l ] = s [ i : r ] (4) s[i-l:r-l]=s[i:r]\tag{4} s[i−l:r−l]=s[i:r](4)
(a)若 z [ i − l ] < r − i + 1 z[i-l] < r-i+1 z[i−l]<r−i+1,那么 s [ i − l : i − l + z [ i − l ] − 1 ] = s [ i : i + z [ i − l ] − 1 ] = s [ 0 : z [ i − l ] − 1 ] (5) s[i-l:i-l+z[i-l]-1]=s[i:i+z[i-l]-1]=s[0:z[i-l]-1] \tag{5} s[i−l:i−l+z[i−l]−1]=s[i:i+z[i−l]−1]=s[0:z[i−l]−1](5) s [ i − l + z [ i − l ] ] = s [ i + z [ i − l ] ] ≠ s [ z [ i − l ] ] (6) s[i-l+z[i-l]]=s[i+z[i-l]] \ne s[z[i-l]]\tag{6} s[i−l+z[i−l]]=s[i+z[i−l]]=s[z[i−l]](6)
因此 z [ i ] = z [ i − l ] (7) z[i] = z[i-l]\tag{7} z[i]=z[i−l](7)
(b)若 z [ i − l ] ≥ r − i + 1 z[i-l] \ge r-i+1 z[i−l]≥r−i+1,那么我们可以扩展 (4) 式 s [ i − l : r − l ] = s [ i : r ] = s [ 0 : r − i ] (8) s[i-l:r-l]=s[i:r]=s[0:r-i] \tag{8} s[i−l:r−l]=s[i:r]=s[0:r−i](8)
这时我们对后续字符进行暴力枚举: z [ i ] = r − i + 1 + ( s [ r : n − 1 ] 与 s [ r − i + 1 : n − 1 ] 的 最 长 公 共 前 缀 区 间 长 度 ) (9) z[i]=r-i+1+(s[r:n-1]与s[r-i+1:n-1]的最长公共前缀区间长度)\tag{9} z[i]=r−i+1+(s[r:n−1]与s[r−i+1:n−1]的最长公共前缀区间长度)(9)
(2)如果 i > r i> r i>r,说明当前还没有访问过 s [ i ] s[i] s[i],那么我们直接从 s [ i ] s[i] s[i] 开始暴力求解即可。
需要注意,每次处理完,需要判断是否更新 [ l , r ] [l,r] [l,r] 区间。
3、实现
vector<int> z_function(string s) {
int sLength = s.length(), left = 0, right = 0;
vector<int> z(sLength);
for (int i = 1; i < sLength; ++i) {
if (i <= right) {
if (z[i - left] < right - i + 1) {
z[i] = z[i - left];
}
else {
z[i] = right - i + 1;
while (i + z[i] < sLength && s[i + z[i]] == s[z[i]]) {
++z[i];
}
}
}
else {
z[i] = 0;
while (i + z[i] < sLength && s[i + z[i]] == s[z[i]]) {
++z[i];
}
}
if (i + z[i] - 1 > right) {
left = i;
right = i + z[i] - 1;
}
}
return z;
}
不难发现,两个 else 分支可以合并。因此,代码可以化简为:
vector<int> z_function(string s) {
int sLength= s.length(), left = 0, right = 0;
vector<int> z(sLength);
for (int i = 1; i < sLength; ++i) {
if (i <= right && z[i - left] < right - i + 1) {
z[i] = z[i - left];
}
else {
z[i] = max(0, right - i + 1);
while (i + z[i] < sLength && s[i + z[i]] == s[z[i]]) {
++z[i];
}
}
if (i + z[i] - 1 > right) {
left = i;
right = i + z[i] - 1;
}
}
return z;
}
上述代码从 i = 1 i=1 i=1 开始计算 z [ i ] z[i] z[i] 是因为 i = 0 i=0 i=0 对应的 [ l , r ] [l,r] [l,r] 区间为 [ 0 , n − 1 ] [0,n-1] [0,n−1],相当于暴力求解。
sumScores 的实现如下:
long long sumScores(string s) {
auto z = z_function(s);
return accumulate(z.begin(), z.end(), (long long)0) + s.length();
}

版权声明
本文为[coding-hwz]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_37950545/article/details/124262186
边栏推荐
- Online Excel to CSV tool
- QT QML component library records owned by QML except basic components
- C reads excel specific data into specific columns of DataGridView
- How to make Jenkins job run automatically after startup
- 服务雪崩效应
- 在线时序流程图制作工具
- [leetcode refers to the two numbers of offer 57. And S (simple)]
- 2022 - 04 - 24 Daily: Current Progress and Open Challenges of Applied Deep Learning in Biological Sciences
- OpenFeign的参数传递之数组和集合类型
- Resolve the "chromedriver executable needs to be in path" error
猜你喜欢

Tsinghua University | webface260m: benchmark for million level deep face recognition (tpami2022)
![[※ leetcode refers to offer 46. Translate numbers into strings (medium)]](/img/72/fbdc5d14dada16cd211c99cd8f9d31.png)
[※ leetcode refers to offer 46. Translate numbers into strings (medium)]

Question brushing plan -- backtracking method (I)

Code cloud download history version process

Online timing flow chart making tool

21. Basic usage of MariaDB

Problem brushing plan -- dynamic programming (IV)

JS prototype and prototype chain

Centos7 builds MySQL master-slave replication from scratch (avoid stepping on the pit)
![[leetcode refers to offer 42. Maximum sum of continuous subarrays (simple)]](/img/e9/497a31cd70b9b21e4cb7845b688d18.png)
[leetcode refers to offer 42. Maximum sum of continuous subarrays (simple)]
随机推荐
openFeign 服务调用
OpenFeign的细节展示
The computer is out of power. How did I pass the terrible interview of Tencent cloud?
setInterval、setTimeout、requestAnimationFrame
[leetcode sword finger offer 10 - II. Frog jumping steps (simple)]
降级和熔断总结
上海确保疫情保供生活物资质量和食品安全
A series of problems of C DataGridView binding list
Mixed use of Oracle column row conversion and comma truncated string
服务熔断的实现
手撕《Google SRE Book》
OpenFeign组件的简介和使用
Opening conditions and process of hystrix circuit breaker and default alternative treatment
2022 - 04 - 24 Daily: Current Progress and Open Challenges of Applied Deep Learning in Biological Sciences
Pycharm Chinese plug-in
FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ‘:app:stripDe
Subcontracting of wechat applet based on uni app
IIS cannot load * woff,*. woff2,*. Solution of SVG file
MySQL back to table
Error message: b04access.00f eve'. Read of address 000001B4