НСП-2#4260

НСП-2 (Həll təhlili)

Məsələdə iki sətirin ən uzun ümumi alt ardıcıllığını (ƏUAA) tapmaq və onu çap etmək lazımdır.

massivini quracağıq, burada dp[i][j] x_{[1 \ldots i]} və y_{[1 \ldots j]} sətirlərinin ƏUAA uzunluğuna bərabərdir. dəyəri orijinal sətirlərin ƏUAA uzunluğuna bərabər olacaq (|x| = n, |y| = m).

massivini hesabladıqdan sonra matrisində hüceyrəsindən -a doğru tərs keçərək ƏUAA-nı bərpa edirik. Cari mövqe üçün aşağıdakı addımları yerinə yetiririk:

Nəticə sətiri və sətirlərinin ən uzun ümumi alt ardıcıllığını özündə saxlayacaq.

Misal

Misalda verilən iki sətir üçün ən uzun ümumi alt ardıcıllığın (ƏUAA) tapılmasını nəzərdən keçirək.

Ümumi alt ardıcıllığın axtarışı (i, j) = (6, 7) mövqeyindən başlayır.

y[6] \ne x[7]: maksimum dəyərə sahib qonşu hüceyrələrdən birinə keçirik, məsələn, .

y[5] \ne x[7]: -ya keçirik.

y[5] = x[6] = '': diaqonal üzrə keçid edirik və '' hərfini ƏUAA-ya daxil edirik.

Alqoritmin reallaşdırılması

Giriş sətirlərini və elan edirik. Onların ƏUAA-nı tapmaq üçün massivindən istifadə edirik.

#define MAX 1001
int dp[MAX][MAX];
string x, y, res;

Giriş sətirlərini oxuyuruq və onlara ön tərəfdən boşluq əlavə edirik ki, indeksləşmə -dən başlasın.

cin >> x; n = x.length(); x = " " + x;
cin >> y; m = y.length(); y = " " + y;

ƏUAA-nı tapırıq.

for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
  if (x[i] == y[j])
    dp[i][j] = dp[i - 1][j - 1] + 1;
  else
    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);

sətirində ƏUAA-nı qururuq.

i = n; j = m;
while (i >= 1 && j >= 1)
  if (x[i] == y[j])
  {
    res = res + x[i];
    i--; j--;
  }
  else
  {
    if (dp[i - 1][j] > dp[i][j - 1])
      i--;
    else
      j--;
  }

Nəticə sətirini tərs çevirir və çıxışa veririk.

reverse(res.begin(), res.end());
cout << res << endl;