общие подпоследовательности

Условие задачи

Условие

Даны две последовательности и длины и .

Здесь подпоследовательность — это последовательность, полученная путем удаления из нуля или более элементов и объединения оставшихся элементов без изменения порядка.

Для и мы различаем две подпоследовательности, если наборы индексов удаленных элементов различны, даже если подпоследовательности одинаковы по содержанию.

В скольких парах подпоследовательности и подпоследовательности эти две подпоследовательности совпадают по содержанию? (=> количество различных способов так удалить из и из так чтобы множества совпадали по содержанию)

По простому модулю .

Примеры

входные данныевыходные данные
2 2
1 3
3 1
3

Решение

Решение

  1. Двумерное — количество подходящих подпоследовательностей, если рассмотреть префикс в и префикс в .
  2. Начальные значения состояний — (пустое множество подходит)
  3. Считаем опять двумя циклами, :
  • если ,
  • иначе.
  1. Ответ —

Маленькая оптимизация. , чтобы было решение за надо сделать оптимизацию префиксных сумм, так как мы для подсчёта делаем запрос суммы на прямоугольники .

cin >> n >> m;
vector<int> s(n), t(m);
for (int i = 0; i < n; i++) cin >> s[i];
for (int i = 0; i < m; i++) cin >> t[i];

vector<vector<int>> dp(n + 1, vector<int>(m + 1));
vector<vector<int>> sum(n + 1, vector<int>(m + 1));

dp[0][0] = 1;
sum[0][0] = 1;

for (int i = 0; i <= n; i++) sum[i][0] = 1;
for (int j = 0; j <= m; j++) sum[0][j] = 1;

for (int i = 1; i <= n; i++) {
  for (int j = 1; j <= m; j++) {
    if (s[i - 1] == t[j - 1]) {
      dp[i][j] = sum[i - 1][j - 1];
    }
    sum[i][j] = add(dp[i][j],
                    sub(add(sum[i - 1][j], sum[i][j - 1]), sum[i - 1][j - 1]));
  }
}
cout << sum[n][m];