Sum [I] [J] indicates the number of occurrences of cow attribute J from 1st to header I
Therefore, the question requirements are equivalent:
Satisfy
Sum [I] [0]-sum [J] [0] = sum [I] [1]-sum [J] [1] = ..... = sum [I] [k-1]-sum [J] [k-1] (j <I)
The largest I-j in
Convert the above formula to get
Sum [I] [1]-sum [I] [0] = sum [J] [1]-sum [J] [0]
Sum [I] [2]-sum [I] [0] = sum [J] [2]-sum [J] [0]
......
Sum [I] [k-1]-sum [I] [0] = sum [J] [k-1]-sum [J] [0]
Set C [I] [Y] = sum [I] [Y]-sum [I] [0] (0 <Y <K)
Initial Condition C [0] [0 ~ K-1] = 0
Therefore, only the largest I-j in C [I] [] = C [J] [] is required, where 0 <= j <I <= n.
C [I] [] = C [J] [] that is, two-dimensional array C [] [] the values of the columns corresponding to row I and row J are equal,
Then the original question is converted to the distance I-j between the two equal and farthest rows in the C array.
Hash C [I,
In this way, we can efficiently find all J in C [I] = C [J.
Using a chained hash table can effectively avoid conflicts.
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 100000 + 5;const int maxk = 30 + 5;const int mod = 99983;int sum[maxn][maxk], c[maxn][maxk];int head[maxn], next[maxn], v[maxn], ecnt;int n, k;void addedge(int a, int b) { next[ecnt] = head[a]; head[a] = ecnt; v[ecnt] = b; ecnt++;}// BKDR Hash Functionint hash(int *v) { unsigned int seed = 131; // 31 131 1313 13131 131313 etc.. unsigned int hash = 0; for(int i=0; i<k; ++i) hash = hash * seed + v[i]; return (hash & 0x7FFFFFFF) % mod;}int main() { memset(sum, 0, sizeof sum ); memset(c, 0, sizeof c ); memset(head, -1, sizeof head ); ecnt = 0; int ans = 0; addedge(hash(c[0]), 0); scanf("%d%d", &n, &k); for(int i=1; i<=n; ++i) { int a; scanf("%d", &a); for(int j=0; j<k; ++j) { sum[i][j] = sum[i-1][j] + (1&a); c[i][j] = sum[i][j] - sum[i][0]; a >>= 1; } int h = hash(c[i]); for(int j=head[h]; j != -1; j=next[j]) { bool flag = true; for(int p=0; p<k; ++p) if(c[v[j]][p] != c[i][p]) { flag = false; break; } if(flag && ans < i-v[j]) ans = i - v[j]; } addedge(h, i); } printf("%d\n", ans); return 0;}/*7 37672142ans:4*/