общие подпоследовательности
Условие
Даны две последовательности и длины и .
Здесь подпоследовательность — это последовательность, полученная путем удаления из нуля или более элементов и объединения оставшихся элементов без изменения порядка.
Для и мы различаем две подпоследовательности, если наборы индексов удаленных элементов различны, даже если подпоследовательности одинаковы по содержанию.
В скольких парах подпоследовательности и подпоследовательности эти две подпоследовательности совпадают по содержанию? (=> количество различных способов так удалить из и из так чтобы множества совпадали по содержанию)
По простому модулю .
Примеры
входные данные | выходные данные |
---|---|
2 2 1 3 3 1 | 3 |
Решение
Решение
- Двумерное — количество подходящих подпоследовательностей, если рассмотреть префикс в и префикс в .
- Начальные значения состояний — (пустое множество подходит)
- Считаем опять двумя циклами, :
- если ,
- иначе.
- Ответ —
Маленькая оптимизация. , чтобы было решение за надо сделать оптимизацию префиксных сумм, так как мы для подсчёта делаем запрос суммы на прямоугольники .
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];