I'll outline a basic approach:
std::map<std::string, size_t> position;
for (size_t i=0; i<checksums.size(); ++i)
{
std::map<std::string, int>::iterator prev=position.find(checksums[i]);
if (prev == position.end())
{
position.insert(std::make_pair(checksums[i], i));
}
else
{
size_t j=prev->first;
positions.erase(prev);
// Everything between index #j and index #i
}
}
I haven't tested if this compiles, if not, it's a minor typo somewhere.
You did not specify how ambiguous situations are handled. I.e., a list of {"foo", "bar", "baz", "foo", "foobar", "foo"} -- whether you're looking for the entries just before the 1st and the 2nd foo, or the 1st and the 3rd foo. My proposed solution, of course, assumes the former, but it wouldn't be too hard to adjust it for the latter.
Also, some further refinements on the algorithms are also possible. For example, it's possible to combine the find/compare/insert operation into a single operation. How to do that, is going to be your homework assignment. Hint: look at the return value of std::map::insert().
EDIT: this finds the matching ranges only. Turning the result into, essentially, a vector of false/true values is not very complicated. You can just initialize the vector to all false values, and when you find the matching range, set every element after j and before i to true.