# 位运算求最长公共子序列

### 简单动态规划

$f_{i,j} = \begin{cases} f_{i-1, j-1} + 1 & (A_j = B_i) \\ \max(f_{i, j-1}, f_{i-1, j}) & (A_j \ne B_i) \end{cases}$

$\begin{cases} f_{i,j} \ge f_{i-1,j} \\ f_{i,j} \ge f_{i,j-1} \\ |f_{i,j} - f_{i,j-1}| \le 1 \end{cases}$

$$f$$ 的同一行内是 单调不减 并且 相邻两个相差不超过一

### 矩阵 $$M$$

$f_{i,j} = \sum_{k=1}^j M_{i,k}$

### 转移方式

M[i - 1]: [1  0  0  0  0  0  0][1  0  0  0][1][1][1][1][1]
p[B[i]] : [0  1  0  1  1  0  0  0  1  0  0  0  1  1  0  0]
^                                            ^
|                                            |
j = |A|                                      j = 1


M[i] :    [0  0  0  0  1  0  0  0  1  0  0  1  1  1  1  1]


### 转移实现

X :       [1  1  0  1  1  0  0  1  1  0  0  1  1  1  1  1]


          [1  1  0  1  1  0  0][1  1  0  0][1][1][1][1][1]
- [0  0  0  0  0  0  1  0  0  0  1  1  1  1  1  1]
--------------------------------------------------
[1  1  0  1  0  1  1][1  0  1  1][0][0][0][0][0]


          [0  0  0  0  1  1  1][0  1  1  1][1][1][1][1][1]


$M_i = ((X-((M_{i-1}\ \texttt{<<}\ 1) + 1))\ \texttt{xor}\ X)\ \texttt{and}\ X、$

### 参考代码

LOJ 提交入口

/*
* Author : _Wallace_
* Source : https://www.cnblogs.com/-Wallace-/
* Problem : LOJ #6564. 最长公共子序列
* Standard : GNU C++ 03
* Optimal : -Ofast
*/
#include <algorithm>
#include <cstddef>
#include <cstdio>
#include <cstring>

typedef unsigned long long ULL;

const int N = 7e4 + 5;
int n, m, u;

struct bitset {
ULL t[N / 64 + 5];

bitset() {
memset(t, 0, sizeof(t));
}
bitset(const bitset &rhs) {
memcpy(t, rhs.t, sizeof(t));
}

bitset& set(int p) {
t[p >> 6] |= 1llu << (p & 63);
return *this;
}
bitset& shift() {
ULL last = 0llu;
for (int i = 0; i < u; i++) {
ULL cur = t[i] >> 63;
(t[i] <<= 1) |= last, last = cur;
}
return *this;
}
int count() {
int ret = 0;
for (int i = 0; i < u; i++)
ret += __builtin_popcountll(t[i]);
return ret;
}

bitset& operator = (const bitset &rhs) {
memcpy(t, rhs.t, sizeof(t));
return *this;
}
bitset& operator &= (const bitset &rhs) {
for (int i = 0; i < u; i++) t[i] &= rhs.t[i];
return *this;
}
bitset& operator |= (const bitset &rhs) {
for (int i = 0; i < u; i++) t[i] |= rhs.t[i];
return *this;
}
bitset& operator ^= (const bitset &rhs) {
for (int i = 0; i < u; i++) t[i] ^= rhs.t[i];
return *this;
}

friend bitset operator - (const bitset &lhs, const bitset &rhs) {
ULL last = 0llu; bitset ret;
for (int i = 0; i < u; i++){
ULL cur = (lhs.t[i] < rhs.t[i] + last);
ret.t[i] = lhs.t[i] - rhs.t[i] - last;
last = cur;
}
return ret;
}
} p[N], f, g;

signed main() {
scanf("%d%d", &n, &m), u = n / 64 + 1;
for (int i = 1, c; i <= n; i++)
scanf("%d", &c), p[c].set(i);
for (int i = 1, c; i <= m; i++) {
scanf("%d", &c), (g = f) |= p[c];
f.shift(), f.set(0);
((f = g - f) ^= g) &= g;
}
printf("%d\n", f.count());
return 0;
}

posted @ 2020-11-28 16:13  -Wallace-  阅读(5594)  评论(3编辑  收藏  举报