题意:题目给定一颗二叉树,前序遍历二叉树的时候产生一个01的欧拉序列,输出某个01串在此序列中出现了几次。
总结:真是弱。。。。我居然模拟查找二叉树的生成,这可能退化到N^2。。。,引用了一个结论:
http://www.cppblog.com/hanfei19910905/archive/2012/07/02/181144.html
nlogn的算法生成静态二叉树,mark一下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#pragma comment(linker, "/STACK:36777216")
using namespace std;
const int N = 600050;
char s[N << 1],p[N];
int next[N],n,a[N],idx,lenp,lens,tot;
int left[N],right[N],stack[N],top;
bool vis[N];
set<int> myset;
void init(int key){
myset.clear();
top = 0;
for(int i = 1;i <= n;i ++)
left[i] = right[i] = -1;
myset.insert(key);
}
void insert(int key){
// printf("key:%d ",key);
myset.insert(key);
set<int> ::iterator less,more;
more = less = myset.lower_bound(key);
if(less != myset.begin()){
less --;
if(right[*less] == -1) {right[*less] = key;
// printf("less:%d\n",*less);
return ;
}
}
more ++;
if(more != myset.end() && left[*more] == -1) left[*more] = key;
// printf("more:%d\n",*more);
}
void setNext(){
int j = 0 , k = -1;
next[j] = k;
while(j < lenp){
if(k == -1 || p[j] == p[k]){
if(p[j + 1] == p[k + 1]) next[++ j] = next[++ k];
else next[++ j] = ++k;
}
else k = next[k];
}
}
void dfs(int cur){
memset(vis,false,sizeof(vis));
top = 0;
stack[++ top] = cur;
while(!vis[cur]){
int u = stack[top];
s[lens ++] = '0' + (u & 1);
int v = left[u];
if(v != -1 && !vis[v]) {stack[++ top] = v;continue;}
v = right[u];
if(v != -1 && !vis[v]) {stack[++ top] = v; continue;}
top --;
vis[u] = 1;
}
}
int kmp(){
int i = 0,j = 0;
int Count = 0;
while(i < lens){
if(j == -1 || s[i] == p[j]){
i ++,j ++;
if(j == lenp) Count ++;
}
else j = next[j];
}
return Count;
}
int main(){
// freopen("input.txt","r",stdin);
int cas;
scanf("%d",&cas);
for(int t = 1;t <= cas;t ++){
scanf("%d",&n);
for(int i = 0;i < n;i ++)
scanf("%d",&a[i]);
scanf("%s",p);
init(a[0]);
for(int i = 1;i < n;i ++)
insert(a[i]);
// printf("LLLL:%d\n",left[5]);
lens = 0;
dfs(a[0]);
s[lens] = '\0';
lenp = strlen(p);
// printf("s:%s\n",s);
setNext();
int ans = kmp();
printf("Case #%d: %d\n",t,ans);
}
return 0;
}