这个建树的过程用了树状数组+二分找区间的做法,很麻烦。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
const int maxn=6e5+9;
int a[maxn];
char s[maxn<<1];
int top,tt=0,f[maxn];
char c[maxn];
int n;
int lon,root=0;
set <int> ss;
struct
{
int l,r,f,key;
}tr[maxn];
int tree[maxn];
void add(int x)
{
for(int i=x;i<=n;i+=i&-i)
tree[i]++;
}
int getsum(int x)
{
int ret=0;
for(int i=x;i>=1;i-=i&-i)
ret+=tree[i];
return ret;
}
void insert(int tmp)
{
// cout<<tmp<<endl;
add(tmp);
int t;
int ll=-1,rr=-1,l,r,mid,nn=getsum(tmp);
if(getsum(n)==1) t=0;
else
{
if(nn>1)
{
l=1,r=tmp;
while(l<r)
{
mid=l+r>>1;
if(getsum(mid)<nn-1) l=mid+1;
else r=mid;
}
ll=f[l]-1;
}
if(getsum(n)-nn)
{
l=tmp,r=n;
while(l<r)
{
mid=l+r>>1;
if(getsum(mid)<=nn) l=mid+1;
else r=mid;
}
rr=f[l]-1;
}
}
if(ll!=-1&&tr[ll].r==-1) t=ll;
else if(rr!=-1) t=rr;
else t=0;
// printf("%d %d\n",tmp,t);
while(tr[t].key!=-1)
{
if(tmp>tr[t].key)
{
if(tr[t].r==-1)
{
tr[t].r=++lon;
tr[lon].f=t;
}
t=tr[t].r;
}
else
{
if(tr[t].l==-1)
{
tr[t].l=++lon;
tr[lon].f=t;
}
t=tr[t].l;
}
}
tr[t].key=tmp;
}
int find(int tmp)
{
int t=root;
while(s[++top]=tr[t].key%2,tr[t].key!=tmp)
{
if(tmp>tr[t].key) t=tr[t].r;
else t=tr[t].l;
}
return t;
}
int getnext(int now)
{
int t=now;
if(tr[t].r!=-1)
{
t=tr[t].r;
while(s[++top]=tr[t].key%2,tr[t].l!=-1)
{
t=tr[t].l;
}
}
else
{
t=tr[t].f;
while(s[++top]=tr[t].key%2,tr[t].key<tr[now].key)
{
t=tr[t].f;
}
}
return t;
}
int next[maxn];
void kmp(char a[],int n)
{
for(int i=1;i<=n;i++)
a[i]-='0';
next[0]=0;
next[1]=0;
for(int i=2;i<=n;i++)
{
int t=i-1;
while(t&&a[i]!=a[next[t]+1])
t=next[t];
next[i]=next[t]+(a[i]==a[next[t]+1]);
}
}
void solve()
{
memset(tree,0,sizeof(tree));
top=lon=0;
memset(tr,-1,sizeof(tr));
for(int i=1;i<=n;i++)
insert(a[i]);
int now=find(1);
for(int i=1;i<n;i++)
{
now=getnext(now);
}
if(now!=0)
{
now=tr[now].f;
while(s[++top]=tr[now].key%2,now!=0)
now=tr[now].f;
}
scanf("%s",c+1);
int m=strlen(c+1);
kmp(c,m);
int ans=0;
for(int i=1,t=1;i<=top;i++)
{
if(s[i]==c[t])
{
if(t==m)
{
t=next[t]+1;
ans++;
}
else t++;
}
else
{
t=t-1;
while(t&&s[i]!=c[next[t]+1])
t=next[t];
t=next[t]+(s[i]==c[next[t]+1])+1;
}
}
printf("Case #%d: %d\n",++tt,ans);
for(int i=1;i<=n;i++)
ss.erase(i);
}
int main()
{
// freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
f[a[i]]=i;
}
solve();
}
return 0;
}