//题意:题意极其抽象,看这个链接優YoU姐那里有题意以及分析,这里看了她的思路写了代码,并学了用链表创建hash表,虽然过程很曲折,改了好久。这里我发一下我wa的一些情况:1).边界 n=4 k= 4 1 2 4 8; 2)n=1 k= 5 3; 3) n = 1 k = 2 3;主要就这三种
//思路:生成一张hash表然后查找,其中记得有一个思想转换很难,其他就是基础编码了。(刚开始用的动态申请 空间并释放空间)
//50628K 625MS
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
typedef class node{
public:
int idx;
class node *next;
node(){
next = 0;
}
}htable;
int n, k;
htable *hashtable[150000];
int maxlen;
int cow[100010][40];
int sum[100010][40];
int c[100010][40];
bool cmp(int l_idx, int n_idx)//l_idx当前这个key下链表中的唯一的值,n_idx传进来的下标
{
for(int i = 0; i < k; i++){
if(c[l_idx][i] != c[n_idx][i])
return false;
}
return true;
}
void Hash(int i)
{
//init key
int key = 0; //生成键
for(int j = 1; j < k; j++){ //自制生成键的公式
key += c[i][j];
}
if(key < 0)
key *= -1;
key = key%149999;
//operate key
if(!hashtable[key]){ //若没有该键则生成该键
htable *p = new htable;
p -> idx = i;
hashtable[key] = p;
}else{
htable *pn = hashtable[key];
if(cmp(pn->idx, i)){
//若键值都相同更新最大区间即可,不用添加新的元素进来,每次都是和第一次添加的元素比较
maxlen = (i - (pn -> idx)) > maxlen ? (i - (pn -> idx)) : maxlen;
return ;
}else{
//若键相同值不同则通过链表生成一个新的值并添加在原有的键上
while(pn -> next){
if(cmp(pn->next->idx, i)){
//若键值都相同更新最大区间即可,不用添加新的元素进来,每次都是和第一次添加的元素比较
maxlen = (i - (pn -> next -> idx)) > maxlen ? (i - (pn -> next -> idx)) : maxlen;
//这里注意链表下标idx别写错了改了好久才发现
return ;
}
pn = pn -> next;
}
htable* temp = new htable;
temp -> idx = i;
pn -> next = temp;
}
}
return ;
}
int main()
{
while(scanf("%d%d", &n, &k) != EOF){
//init
int var;
memset(hashtable, 0, sizeof(hashtable));
maxlen = 0;
for(int i = 0; i < k+1; i++){
cow[0][i] = 0;
sum[0][i] = 0;
c[0][i] = 0;
}
Hash(0);
for(int i = 1; i <= n; i++){
scanf("%d", &var);
for(int j = 0; j < k; j++){
cow[i][j] = var % 2;
sum[i][j] = sum[i-1][j] + cow[i][j];
c[i][j] = sum[i][j] - sum[i][0];
var /= 2;
}
//hash
Hash(i);
}
printf("%d\n", maxlen);
}
return 0;
}