题目描述:
给N个数(标号为1-N)按顺序建一棵二叉排序树,然后按数字从小到大遍历这棵树,每走过一个标号为奇数的节点记录1,偶数记录0,访问完所有节点回到地面上之后便能得到一串0-1序列,之后给另外一个0-1串s,问遍历得到的串包含多少个s(可以重叠) n不大于600000
北大出的题还是很好的,题目读起来很简单,不是什么模板题不是超难的论文题也不是特简单的水题。解题思路很清晰,但却需要不断优化,否则10^5的数据很容易超时或者爆内存。这题改了N次,在TLE,MLE,RE折磨N次之后才勉强A掉
题目很简单,但有三个地方需要注意:
- 建树不能只是模拟插入过程递归写,N为10^5,给0、1、2、3.......N 时会超时,需要稳定Nlog(N)
- 遍历的时候不能递归写,会栈溢出
- 字符串匹配next数组需要处理到匹配串的长度,即需要算出next[m]
另外,建树遍历什么的一定不要用动态内存写,会很麻烦,最好提前开个数组
#include<iostream>
#include<cstdio>
#include<cstring>
#include<iterator>
#include<memory.h>
#include<set>
using namespace std;
bool visited[600005];
char str[1800005];
int cnt,ct,size,res,next[7007];
struct Node{
int num;
Node* left;
Node* right;
};
struct cmp{
bool operator()(const Node* a,const Node* b){
return (a->num)<(b->num);
}
};
Node* stac[1800005];
Node* node = new Node[600005];
set<Node*,cmp> visit;
set<Node*,cmp>::iterator it;
void Next(const char s[]){
memset(next,0,sizeof(next));
int j,t,m;
t=next[0]=-1;
j=0;
m=strlen(s);
while(j<m){
if(t<0||s[j]==s[t]) next[++j]=++t;
else t=next[t];
}
return;
}
void Mat(const char s1[],const char s2[]){
int i,j,m;
m=strlen(s2);
i=j=0;
while(i<ct){
if(j==m) res++;
if(j<0||s1[i]==s2[j]){
i++;
j++;
}
else j=next[j];
}
if(j==m) res++;
}
void dfs(Node* curr){
size=0;
memset(visited,0,sizeof(visited));
stac[size++]=curr;
while(size>0){
curr=stac[size-1];
size--;
if((curr->num)%2) str[ct++]='1';
else str[ct++]='0';
if(!visited[curr->num]){
visited[curr->num]=true;
if(curr->right){
stac[size++]=curr;
stac[size++]=curr->right;
}
if(curr->left){
stac[size++]=curr;
stac[size++]=curr->left;
}
}
}
}
int main(){
Node* tree;
Node* tmpNode;
int k,n,num;
char harStr[7007];
while(scanf("%d",&k)!=EOF){
for(int p=1;p<=k;p++){
visit.clear();
ct=res=cnt=0;
tree=NULL;
scanf("%d",&n);
scanf("%d",&num);
node[cnt].num=num;
node[cnt].left=NULL;
node[cnt].right=NULL;
tree=&node[cnt];
cnt++;
visit.insert(tree);
for(int i=1;i<n;i++){
scanf("%d",&num);
node[cnt].num=num;
node[cnt].left=NULL;
node[cnt].right=NULL;
tmpNode=&node[cnt];
cnt++;
it=visit.lower_bound(tmpNode);
if(it!=visit.end()&&((*it)->left==NULL)){
(*it)->left=tmpNode;
}
else{
it--;
(*it)->right=tmpNode;
}
visit.insert(tmpNode);
}
dfs(tree);
scanf("%s",harStr);
Next(harStr);
Mat(str,harStr);
printf("Case #%d: %d\n",p,res);
}
}
return 0;
}