/*
这题卡内存实在是太狗了……
思路很明确,就是几个算法杂糅在一起
刚开始粗糙的思路是建一个二叉搜索树,再按照中序遍历把树的点存一遍,最后跑一遍KMP
然而
二叉搜索树用的set和数组revg,revg[i]存储对于值为i的节点下标
中序遍历用dfs做
本题卡内存,正确的做法应该是
二叉搜索树用的map,因为map是有序且按照第一维升序排列,故可以直接替换revg和set的作用
中序遍历用手工栈做
失分点:
1.卡内存:
出现情况可能是递归爆栈、系统STL库存储空间需要过大、开的数组过多过大
学习的地方:
1.map有序,可以用来二分查找
2.卡内存时处理办法
3.递归爆栈时可以改成手工栈操作
*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <string>
#include <vector>
#include <iterator>
#include <queue>
#include <utility>
#include <set>
#include <stack>
#include <map>
using namespace std;
#define mp make_pair
#define fi first
#define se second
const int MAXN = 600000 + 5;
int ne[MAXN][2];
int nodecnt;
int g[MAXN];//, revg[MAXN];//, vis[MAXN];
char out[MAXN * 3];
//int fa[MAXN];
int outcnt;
int fail[7000 + 5], n;
char mat[7000 + 5];
//set<int>S;
map<int,int>revg;
int sta[MAXN];
int num[MAXN];
void dfs(int mark)
{
memset(num, 0, sizeof num);
int head = 1, rear = 0;
sta[++rear] = mark;
while(head <= rear) {
int u = sta[rear--];
// printf("u = %d\n", u); system("pause");
out[outcnt++] = (g[u] % 2) + '0';
if(num[u] == 0) {
num[u]++;
if(ne[u][0] != -1) {
sta[++rear] = u;
sta[++rear] = ne[u][0];
continue;
}
}
if(num[u] == 1) {
num[u]++;
if(ne[u][1] != -1) {
sta[++rear] = u;
sta[++rear] = ne[u][1];
}
}
}
}
//int const MAXT2 = MAXN * 2;
void failure()
{
fail[0] = 0;
int j = fail[0];
int len = strlen(mat);
for(int i=1; i<len; i++){
while(j && mat[i]!=mat[j])
j = fail[j];
if(mat[i] == mat[j]) j++;
fail[i + 1] = j;
}
}
int match()
{
int res = 0,now = 0,j=0;
int n = strlen(mat);
int m = outcnt;
while(now + n - j <= m){
if(j == n){
res ++;
j = fail[j];
}
while(j && mat[j]!=out[now]) j = fail[j];
if(mat[j] == out[now]){
j++; now++;
}
else{
now++;
}
}
return res;
}
void init(int i){for(int u = 0 ; u < 2 ; u++) ne[i][u] = -1;}
int main()
{
int T; scanf("%d", &T);
for(int cas = 1 ; cas <= T ; cas++) {
revg.clear();
// S.clear();
scanf("%d", &n);
outcnt = 0;
memset(ne, -1, sizeof ne);
for(int i = 1 ; i <= n ; i++) scanf("%d", &g[i]);
revg[0] = 0;
init(1);
init(0);
// vis[0] = 0;
// node[1].init();
revg[g[1]] = 1;
for(int i = 2 ; i <= n ; i++) {
// if(i == 2) {
// printf("node[1] = %d %d\n", node[1].ne[0], node[1].ne[1]);
// }
map<int,int>::iterator it = revg.lower_bound(g[i]);
int t1, t2;
if(it == revg.end()) {
it--;
t2 = 0;
t1 = (*it).se;
}
else {
t2 = (*it).se;
if(it == revg.begin()) t1 = 0;
else {
it--;
t1 = (*it).se;
}
}
// t1 = revg[t1], t2 = revg[t2];
int parent;
if(t1 != 0 && ne[t1][1] == -1) parent = t1, ne[t1][1] = i;
else parent = t2, ne[t2][0] = i;
// printf("t1 = %d, ne[t1] = %d %d, t2 = %d, ne[t2] = %d %d\n", t1, ne[t1][0], ne[t1][1], t2, ne[t2][0], ne[t2][1]);
// node[i].init();
init(i);
revg[g[i]] = i;
// fa[i] = parent;
// S.insert(g[i]);
}
// for(int i = 1; i <= n ; i++) {
// printf("i = %d, u = %d, ne = %d %d\n", i, g[i], ne[i][0], ne[i][1]);
// }
// sort(g + 1, g + 1 + n);
dfs(1);
out[outcnt] = '\0';
// printf("out = %s\n", out);
scanf("%s", mat);
failure();
int res = match();
printf("Case #%d: %d\n", cas, res);
}
return 0;
}