Prefix- and z-functions in C++ (string algorithms)
This will be a somewhat strange answer but the thing is that I can't find anything wrong with your code: it is not that easy to understand what it is doing, but it is only because the algorithms are not the most straightforward in the world; if we compare your code and the algorithms pseudo-code, it's easy to see that they are performing the same computations. Everything seems well-written, the language is used as it should be used... In the end, I only have a few almost-irrelevant remarks left:


The only obvious thing you could do is to templatize your algorithm so that it works for any std::basic_string specialization and not only for std::string.
If you strive for speed and can overcome a little less readability (generally, you don't), you could try to change this piece of code:

if (str[i] == str[pref]) {
    ++pref;
}


into this one:

pref += str[i] == str[pref];


But even then, time it, time it again, and I'm pretty sure that the compiler is somehow smart enough to get rid of that branch for you and that it won't impact the overall speed of the algorithm in any significant way.
You are slightly inconsistent in the way you call the functions: you wrote std::min (/* ... */) but also std::max(/* ... */). You should either put a space everywhere or remove it everywhere, but be consistent.


Well, as you see, there is little to say about what you wrote. It's some pretty good code. Great job writing it! :)