4465
引言
这题是Claris教的,说:我两三年前在bzoj做这题时,只有两个提交,一个是出题人自己交的,还有一个是交出题人代码的。
然后这道原来正解是块状链表+后缀自动机的题目被Claris用bitset暴力匹配吊打了标算。sro Claris!
shift-and算法
由于懒,用的是C++自带的std::bitset。这是道黑题,其具体用法就挂个链接了。
记 std::bitset<1000005>B[10];
对于
对于 00011111000 式的(仅对答案可能存在的 p=(p<<1)&B[C[j]-'0'] 即可。把p左移就相当于把文本串右移。注意第一次不必左移。复杂度大约是
Code
人傻常数大,开了O2才过。
代码轻微压行,不到1KB,比较短。
#include <bitset>
#include <stdio.h>
typedef long long llt;
typedef unsigned uint;typedef unsigned long long ullt;
typedef bool bol;typedef char chr;typedef void voi;
typedef double dbl;
std::bitset<1000005>B[10],p;chr C[1919810];
int main()
{
uint q=0,op,num1,num2,f;scanf("%u",&q);
while(q--)
{
scanf("%u%u",&op,&num1);
if(op)
if(op==1)
{
scanf("%u",&num2);
for(uint i=0;i<10;i++)p=(B[i]>>num2)<<num2,B[i]^=((B[i]>>num1)<<num1)^(p>>(num2-num1));
}
else
{
scanf("%u%s",&num2,C),p=std::bitset<1000005>();
for(f=0;C[f];f++);
p=((~p)<<num1)^((~p)<<(num2-f+1));
for(uint j=0;j<f;j++)p=(j?(p<<1):p)&B[C[j]-'0'];
printf("%d\n",(int)p.count());
}
else
{
scanf("%s",C);
for(f=0;C[f];f++);
for(uint i=0;i<10;i++)p=(B[i]>>num1)<<num1,B[i]^=p^(p<<f);
for(uint i=0;i<f;i++)B[C[i]-'0'][num1+i]=true;
}
}
return 0;
}
后记
第一次写黑题题解,有所勘误恳请指出。
bitset在字符串匹配上有所应用,一般不超过
Claris:这题究竟没有躲过暴力。
还是sro Claris!