Witam!
Mam dwa łańcuchy. Potrzebuję sprawdzić, czy można je zaprezentować jako XYZ i XZY, przy czym Y i Z są niepuste.
Przykładowo, "kacper" i "perkac" lub "ababbabaab" i "abaaabbbab" są takimi łańcuchami.
Mój pomysł to 'zjedzenie' takiego samego początku obu łańcuchów (o ile taki jest), a potem wyszukiwanie LCS (najdłuższego wspólnego podłańcucha) reszty i sprawdzanie czy to, co zostało jest takie same.
Mam problem z implementacją tego LCS - zwraca tylko pojedyńczy wspólny znak. Używam algorytmu http://edu.i-lo.tarnow.pl/inf/alg/001_search/0056.php, ostatnia sekcja. Wszystkie angielskie algorytmy mają złożoność pamięciową O(mn), a ten ma O(n), a zależy mi na pamięci.
bool najkWspPodl(const string& s1, const string& s2, int& p1, int& p2, unsigned& lm) // s1 i s2 są tej samej długosci, p1 -> pozycja lcs w s1, p2 -> --//-- w s2, lm -> długość lcs
{
unsigned n = s1.size();
//int* l0 = new int[n];
//int* l1 = new int[n];
vector<int> l0(n, 0), l1(n); // hmm, RAII jest, ale poco?
//for (unsigned i = 0; i < n; i++)
// l0[i] = 0;
lm = 0;
for (unsigned i = 0; i < n; i++)
{
for (unsigned j = 0; j < n; j++)
{
if (s1[i] == s2[j])
{
l1[j + 1] = 1 + l0[j];
if (l1[j + 1] > lm)
{
lm = l1[j + 1];
p1 = i - lm + 1;
p2 = j - lm + 1;
}
else
{
l1[j + 1] = 0;
goto koniecPetli; // ała, ale szybciej tak, niż boolem
}
}
else
goto koniecPetli;
}
for (unsigned j = 0; j < n; j++)
l0[j] = l1[j];
koniecPetli:;
}
//delete[] l0;
//delete[] l1;
return lm != 0;
}
Od biedy ujdzie też regex "(.*)(.+)(.+)\1\3\2". Ale to nie będzie zbyt szybkie.
Poza tym, na moim komputerze (Windows, MSVC) działa, ale na Linuxie (GCC) wyrzuca SIGSEGV.
Jakby ktoś miał jeszcze jakieś lepsze pomysły to pisać.