当前位置:网站首页>Leetcode 2223 -- sum of total scores of construction string

Leetcode 2223 -- sum of total scores of construction string

2022-04-23 22:06:00 coding-hwz

One 、 Title Description

 Insert picture description here

Two 、 Algorithm

This question is actually the subject of investigation Z Algorithm .

1、 Generalized problem description

For a length of n n n String s s s. Defined function z [ i ] z[i] z[i] Express s s s and s [ i : n − 1 ] s[i:n-1] s[i:n1] The length of the longest common prefix . Give the calculation
z z z The algorithm of . notes : here s [ i : n − 1 ] s[i:n-1] s[i:n1] contain s [ i ] s[i] s[i] and s [ n − 1 ] s[n-1] s[n1].

2、 analysis

And KMP similar , Calculation z [ i ] z[i] z[i] We need to use the experience of the previous calculation process . The core of this algorithm is : Maintained [ l , r ] [l, r] [l,r] Section , Satisfy r = max ⁡ 0 ≤ k < i k + z [ k ] − 1 (1) r = \max \limits_{0 \le k < i}k+z[k]-1\tag{1} r=0k<imaxk+z[k]1(1) l + z [ l ] − 1 = r (2) l+z[l]-1=r\tag{2} l+z[l]1=r(2)
It's not hard to find out , [ l , r ] [l, r] [l,r] It's actually s s s and s [ l : n − 1 ] s[l:n-1] s[l:n1] The longest common prefix interval of . therefore , We can get s [ 0 : r − l ] = s [ l : r ] (3) s[0:r-l]=s[l:r]\tag{3} s[0:rl]=s[l:r](3)
When we need to calculate z [ i ] z[i] z[i] when , It needs to be discussed on a case by case basis :
(1) If i ≤ r i\le r ir, Yes (3) Add... To the starting interval at the left and right ends of the equation at the same time i − l i-l il You can get s [ i − l : r − l ] = s [ i : r ] (4) s[i-l:r-l]=s[i:r]\tag{4} s[il:rl]=s[i:r](4)
(a) if z [ i − l ] < r − i + 1 z[i-l] < r-i+1 z[il]<ri+1, that 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[il:il+z[il]1]=s[i:i+z[il]1]=s[0:z[il]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[il+z[il]]=s[i+z[il]]=s[z[il]](6)
therefore z [ i ] = z [ i − l ] (7) z[i] = z[i-l]\tag{7} z[i]=z[il](7)
(b) if z [ i − l ] ≥ r − i + 1 z[i-l] \ge r-i+1 z[il]ri+1, Then we can expand (4) type 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[il:rl]=s[i:r]=s[0:ri](8)
At this time, we enumerate the following characters : z [ i ] = r − i + 1 + ( s [ r : n − 1 ] And s [ r − i + 1 : n − 1 ] Of most Long Male common front Affix District between Long degree ) (9) z[i]=r-i+1+(s[r:n-1] And s[r-i+1:n-1] The length of the longest common prefix interval )\tag{9} z[i]=ri+1+(s[r:n1] And s[ri+1:n1] Of most Long Male common front Affix District between Long degree )(9)
(2) If i > r i> r i>r, It indicates that you have not visited s [ i ] s[i] s[i], So let's go straight from s [ i ] s[i] s[i] Start solving violence .
We need to pay attention to , After each treatment , You need to judge whether to update [ l , r ] [l,r] [l,r] Section .

3、 Realization

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;
}

It's not hard to find out , Two else Branches can merge . therefore , The code can be reduced to :

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;
}

The above code is derived from i = 1 i=1 i=1 Start calculating z [ i ] z[i] z[i] Because i = 0 i=0 i=0 Corresponding [ l , r ] [l,r] [l,r] Interval is [ 0 , n − 1 ] [0,n-1] [0,n1], It is equivalent to solving by violence .

sumScores The implementation is as follows :

long long sumScores(string s) {
    
    auto z = z_function(s);
    return accumulate(z.begin(), z.end(), (long long)0) + s.length();
}

 Insert picture description here

版权声明
本文为[coding-hwz]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/113/202204232157499594.html