2011 Asia Fuzhou Regional Contest-1005 hdu4125 Moles

来源:互联网 发布:建筑施工安全网络平台 编辑:程序博客网 时间:2024/04/30 08:24


题目描述:

    给N个数(标号为1-N)按顺序建一棵二叉排序树,然后按数字从小到大遍历这棵树,每走过一个标号为奇数的节点记录1,偶数记录0,访问完所有节点回到地面上之后便能得到一串0-1序列,之后给另外一个0-1串s,问遍历得到的串包含多少个s(可以重叠) n不大于600000


北大出的题还是很好的,题目读起来很简单,不是什么模板题不是超难的论文题也不是特简单的水题。解题思路很清晰,但却需要不断优化,否则10^5的数据很容易超时或者爆内存。这题改了N次,在TLE,MLE,RE折磨N次之后才勉强A掉


题目很简单,但有三个地方需要注意:

  1. 建树不能只是模拟插入过程递归写,N为10^5,给0、1、2、3.......N 时会超时,需要稳定Nlog(N)
  2. 遍历的时候不能递归写,会栈溢出
  3. 字符串匹配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;}