Skip to content

Commit 024dc46

Browse files
committed
add bit-lcs and clcs
1 parent 0bef8b3 commit 024dc46

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Collections of some commonly used algorithms.
2020
+ [ ] Square Factorization
2121
+ [x] Lempel-Ziv Factorization
2222
+ [ ] Repetitions
23+
+ [x] CLCS
24+
+ [x] bit-LCS
2325

2426
## Graph Algorithms
2527

@@ -140,3 +142,4 @@ Collections of some commonly used algorithms.
140142
+ [x] Frobenius Equations
141143
+ [x] 最长上升子序列
142144
+ [ ] Stern–Brocot tree
145+
+ [ ] 直线下格点

string-utility/bit-lcs.cc

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* Bit-String Longest Common Subsequence LCS Algorithm
3+
*
4+
* http://www.csse.monash.edu.au/~lloyd/tildeStrings/Alignment/86.IPL.html
5+
*
6+
* time complexity: O(nm/w)
7+
**/
8+
#include <bits/stdc++.h>
9+
typedef long long LL;
10+
11+
const int MAXN = 2000 + 10, SIGMA = 26;
12+
const int W = 62;
13+
int M = 33;
14+
struct Bitset {
15+
LL u[34];
16+
void clr() {
17+
memset(u, 0, sizeof(u));
18+
}
19+
void set(int x) {
20+
u[x / W] |= 1ll << (x % W);
21+
}
22+
Bitset operator |(const Bitset &r) const {
23+
Bitset s;
24+
for (int i = 0; i < M; ++ i) {
25+
s.u[i] = u[i] | r.u[i];
26+
}
27+
return s;
28+
}
29+
void gao(const Bitset &r) {
30+
for (int i = 0; i < M; ++ i) {
31+
u[i] = (u[i] ^ r.u[i]) & r.u[i];
32+
}
33+
}
34+
void sub(const Bitset &r) {
35+
for (int i = 0; i < M; ++ i) u[i] = r.u[i] - u[i];
36+
for (int i = 0; i < M; ++ i) if (u[i] < 0) {
37+
u[i] += 1ll << W; u[i + 1] --;
38+
}
39+
}
40+
void shl() {
41+
for (LL i = 0, c(1); i < M; ++ i) {
42+
u[i] <<= 1; u[i] |= c;
43+
c = u[i] >> W & 1;
44+
u[i] ^= c << W;
45+
}
46+
}
47+
int cnt() const {
48+
int c(0);
49+
for (int i = 0; i < M; ++ i) {
50+
c += __builtin_popcountll(u[i]);
51+
}
52+
return c;
53+
}
54+
} row, as[SIGMA], x;
55+
56+
57+
int main() {
58+
char S[MAXN], T[MAXN];
59+
for (int i = 0; i < SIGMA; ++i) as[i].clr();
60+
scanf("%s%s", S, T);
61+
int n = strlen(S), m = strlen(T);
62+
for (int i = 0; i < n; ++ i) {
63+
as[S[i] - 'a'].set(i);
64+
}
65+
M = n / W + (n % W != 0);
66+
row.clr();
67+
for (int i = 0; i < m; ++i) {
68+
for (int j = 0; j < M; ++j) {
69+
x.u[j] = row.u[j] | as[T[i] - 'a'].u[j];
70+
}
71+
row.shl();
72+
row.sub(x);
73+
row.gao(x);
74+
printf("%d\n", row.cnt());
75+
}
76+
return 0;
77+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Solving Cyclic Longest Common Subsequence in Quadratic Time
3+
* https://arxiv.org/pdf/1208.0396v3.pdf
4+
*
5+
* time complexity: O(nm)
6+
**/
7+
#include <cstring>
8+
#include <algorithm>
9+
10+
const int N = 4000 + 10;
11+
int dp[N][N], from[N][N];
12+
13+
int clcs(char s[], char t[]) {
14+
int n = strlen(s), m = strlen(t);
15+
auto eq = [&](int a, int b) {
16+
return s[(a - 1) % n] == t[(b - 1) % m];
17+
};
18+
dp[0][0] = from[0][0] = 0;
19+
for (int i = 0; i <= n * 2; ++i) {
20+
for (int j = 0; j <= m; ++j) {
21+
dp[i][j] = 0;
22+
if (j && dp[i][j - 1] > dp[i][j]) {
23+
dp[i][j] = dp[i][j - 1];
24+
from[i][j] = 0;
25+
}
26+
if (i && j && eq(i, j) && dp[i - 1][j - 1] + 1 > dp[i][j]) {
27+
dp[i][j] = dp[i - 1][j - 1] + 1;
28+
from[i][j] = 1;
29+
}
30+
if (i && dp[i - 1][j] > dp[i][j]) {
31+
dp[i][j] = dp[i - 1][j];
32+
from[i][j] = 2;
33+
}
34+
}
35+
}
36+
int ret = 0;
37+
for (int i = 0; i < n; ++i) {
38+
ret = std::max(ret, dp[i + n][m]);
39+
// re-root
40+
int x = i + 1, y = 0;
41+
while (y <= m && from[x][y] == 0) ++y;
42+
for (; y <= m && x <= n * 2; ++x) {
43+
from[x][y] = 0, --dp[x][m];
44+
if (x == n * 2) break;
45+
for (; y <= m; ++y) {
46+
if (from[x + 1][y] == 2) break;
47+
if (y + 1 <= m && from[x + 1][y + 1] == 1) {
48+
++y; break;
49+
}
50+
}
51+
}
52+
}
53+
return ret;
54+
}

0 commit comments

Comments
 (0)