Q:

Сравнение двух путей и получение общей части с конца

Создаю код бекапа заменяемых файлов. Имеется:
array<String^>^ FilesToCopy = System::IO::Directory::GetFiles(Path::Combine(pc->OBMFolder(), modName), "*.*", IO::SearchOption::AllDirectories);
/* Создаем бекап */
    if (makeBackUp){
        array<String^>^ FilesInGame = System::IO::Directory::GetFiles(Path::Combine(getGP->ModsFolder(), "SP2", "data"), "*.*", IO::SearchOption::AllDirectories);
        for (int i = 0; i < FilesToCopy->Length; i++){
            String^ FileToCopy = Path::GetFileName(FilesToCopy[i]);
            for (int j = 0; j < FilesInGame->Length; j++){
                String^ FileInGame = Path::GetFileName(FilesInGame[j]);
                if (FileToCopy == FileInGame){
                    String^ NewPackFolder = Path::Combine(pc->OBMFolder(), wnd->GetInputText());
                    if (!Directory::Exists(NewPackFolder)) Directory::CreateDirectory(NewPackFolder);

                    ТУТ ПРОБЛЕМА, Нужно получить максимально возможную общуй часть для двух входных путей, и скопировать файл в новую папку сохраняя иерархию каталогов.
                }
            }
        }
    }

А проблема в следующем:
Нужно сравнить два полных имени файла и вернуть их максимально общую часть с конца строк.
Например:
Путь А: С:\Folder\docs\file.txt
Путь Б: E:\Directory\Folder1\docs\file.txt

Нужно получить на выходе 
docs\file.txt

Пока не очень понимаю как правильно реализовать данную функцию. Нужен алгоритм с примером. Не важно C# или C++CLI, я адаптирую под себя сам, просто на C# больше народу.

A:

Ну как же, вопрос с меткой C# и никто не предложил Linq-вариант?
Исправляем:
var s1 = @"С:\Folder\docs\file.txt";
var s2 = @"E:\Directory\Folder1\docs\file.txt";
var s3 = new string(
    s1.Reverse()
      .Zip(s2.Reverse(), (c1, c2) => c1 == c2 ? c1 : -1)
      .TakeWhile(x => x > -1)
      .Reverse()
      .Select(x => (char)x)
      .ToArray());
Console.WriteLine(s3);

Выведет \docs\file.txt
Если вместо -1 использовать (char)0 и в TakeWhile поправить условие, то можно выкинуть Select
В C++/CLI переведете сами.
Почти то же самое, но сравниваем по секциям (специфично именно для путей), более правильное решение:
var s1 = @"C:\Folder\docs\file.txt";
var s2 = @"E:\Directory\Folder1\docs\file.txt";
var s3 = string.Join("\\",
            EnumerateParts(s1)
                .Zip(EnumerateParts(s2), (p1, p2) => p1 == p2 ? p1 : null)
                .TakeWhile(p => p != null)
                .Reverse());
Console.WriteLine(s3);

Где EnumerateParts:
static IEnumerable<string> EnumerateParts(string path)
{
    var root = Path.GetPathRoot(path);
    while (path != root)
    {
        yield return Path.GetFileName(path);
        path = Path.GetDirectoryName(path);
    }
    yield return root;
}

