P10920 题解
DaiRuiChen007 · · 题解
Problem Link
题目大意
给定
n 位 01 串S ,其中有一些通配符可以任意换成0/1 ,求最大的k 使得存在i 满足S[i,i+k-1]=S[i+k,i+2k-1] 。数据范围:
n\le 10^5 。
思路分析
这个问题显然很难做到 polylog 或者根号,因此考虑 std::bitset 优化。
从大到小枚举 std::bitset 维护为
那么我们检验
对于 std::bitset 字长。
对于
如果一个块非空,那么只有其最长 __builtin_clz 和 __builtin_ctz 维护,需要手写 bitset。
时间复杂度
代码呈现
#include<bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int MAXN=1e5+5,S=1575;
char s[MAXN];
int n;
ull f[S],g[S],t[S];
bool chk(int x) {
for(int i=0,c=0;i+x<n;++i) {
if(s[i]!='?'&&s[i+x]!='?'&&s[i]!=s[i+x]) c=0;
else ++c;
if(c>=x) return true;
}
return false;
}
void solve() {
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
scanf("%d%s",&n,s);
for(int i=0;i<n;++i) {
if(s[i]=='0') f[i>>6]|=1ull<<(i&63);
if(s[i]=='1') g[i>>6]|=1ull<<(i&63);
}
for(int i=n/2;i>64;--i) {
memset(t,0,sizeof(t));
int ed=(n-i)>>6;
for(int j=0,b=i>>6,r=i&63;j<=ed;++j) {
ull F=f[j+b]>>r,G=g[j+b]>>r;
if(r) F|=f[j+b+1]<<(64-r),G|=g[j+b+1]<<(64-r);
t[j]=(F&g[j])|(G&f[j]);
}
for(int c=(n-i);c<((ed+1)<<6);++c) t[c>>6]|=1ull<<(c&63);
int x=t[0]?__builtin_clzll(t[0]):64;
for(int j=1;j<=ed;++j) {
if(!t[j]) {
if((x+=64)>=i) return printf("%d\n",i),void();
} else {
if(x+__builtin_ctzll(t[j])>=i) return printf("%d\n",i),void();
x=__builtin_clzll(t[j]);
}
}
}
for(int i=min(n/2,64);i;--i) if(chk(i)) return printf("%d\n",i),void();
puts("0");
}
signed main() {
int T; scanf("%d",&T);
while(T--) solve();
return 0;
}