题意分析
2223. 构造字符串的总得分和 - 力扣(LeetCode)
这题就是一个求前后缀匹配的问题,这种类型有个通常的模板——Z函数,只要弄明白z函数就可以了。
算法思路
z函数实现:
- 我们维持一个数组Z(n),用来记录每个i的匹配长度
- 判断s[z[i]]==s[i+z[i]],如果相等就z[i]++;不等就不用做
- 考虑到在[i,i+z[i]-1]区间中,将区间标记维[l,r],只要落到这个区间中的i是不需要再额外算的(因为已经算过了,不需要重复算),我们可以将z[i-l]转移给z[i]
- 但是如果z[i-l]长度超过了小盒子的长度,则就要将r-i+1赋值给z[i],然后盒子外的暴力比较一番。
- 最后更新盒子,如果i+z[i]>r了,那么比较就到盒子外去了,这时要更新l=i,r=i+z[i]-1,因为i+z[i]那里没有匹配成功。
代码实现
class Solution {
public:
long long sumScores(string s) {
int n=s.length();
vector<int> z(n,0);
z[0]=n;
long long ans=z[0];
for(int i=1,l=0,r=0;i<n;i++){
if(i<=r) z[i]=min(z[i-l],r-i+1);
while(s[z[i]]==s[i+z[i]]) z[i]++;
if(i+z[i]>r) l=i,r=i+z[i]-1;
ans+=z[i];
}
return ans;
}
};
解题总结
z函数是kmp的一种拓展,用来解决前后缀问题简直不要太方便。本质就是将比较过的部分跳过不进行比较,但大大降低了时间复杂度。