#include <cstring>
#include <iostream>
#include <fstream>
#include <vector>

int main()
{
    char buffer[0x10000]; // extent if needed or make it dynamic if you like

    std::ifstream in("list.txt", std::ios::binary);
    std::ofstream out("nodup.txt", std::ios::binary);

    //std::cin.rdbuf(in.rdbuf());
    //std::cout.rdbuf(out.rdbuf());

    std::ios_base::sync_with_stdio(false);

    while (in.getline(buffer,sizeof(buffer)))
    {
        auto n = strlen(buffer);
        //buffer[n-1] = ';';      // makes our live easier
        auto h = buffer;        // head
        auto e = h + strlen(h); // end

        for (auto i=0; i<3; ++i)
        { // skip three fields
            do if (*h == '\0')
            {
                goto Print;
            }
            while (*h++ != ';');
        }

        while (true)
        {
            while (*h == ';')
                ++h;
            if (*h == '\0')
                break;

            auto t = h; // tail
            while (*t++ != ';')
               ;

            char *z = NULL; // first duplicate we find, if any
            while (*t != '\0')
            { // until the end of the line
                auto s = t; // remember the current tail field's start

                for (auto p=h;; ++t)
                { // p iterates over the head field
                    auto c = *p++;

                    if (c != *t)
                    { // tail field doesn't match
                        while (*t++ != ';')
                           ;
                        break;
                    }

                    if (c == ';')
                    { // tail field does match
                        *s = '\0';
                        if (z == NULL)
                            z = s;
                        ++t;
                        break;
                    }
                }
            }
            // next head field
            while (*h++ != ';')
               ;
            // before we continue we're going *remove* the duplicates...
            if (z != NULL)
            { // ...if there were any
                auto q = z;
                while (z != e)
                {
                    while (*++z != ';')
                       ;
                    while (*z != '\0')
                        *q++ = *z++;
                }
                *q = '\0'; e = q;
            }
        }

Print:

        n = strlen(buffer); // size will have changed if there were dups
        //buffer[n-1] = '\n'; // we've set it to ';' before for convenience
        buffer[n] = '\n';
        out << buffer;
    }

    if (!in.eof()) {
        std::cerr << "line probably too long (please extend buffer size)\n";
        exit(1);
    }

    return 0;
}
