题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3441
先把源码插入tree中,然后统计能够重叠的情况和不能重叠的情况,并把信息存储起来,最后依据给出的0 1输出统计的结果。考虑到内存,用数组不用指针。这种用数组写出的trie树可以过。
#include <iostream> #include<cstdio> #include<cstring> using namespace std; const int nn=26,maxn=1e5+10; int N,top,root,tp; char str[maxn],keyword[10]; struct node{ int next[nn],c[2]; int loc; }tree[6*maxn]; int newnode(){ for(int i=0;i<nn;i++)tree[top].next[i]=-1; tree[top].c[0]=tree[top].c[1]=0; tree[top].loc=-1; return top++; } void insert_t(int dex){ int i=dex,p=root; while(i<dex+6&&str[i]){ int id=str[i]-97; if(tree[p].next[id]==-1)tree[p].next[id]=newnode(); p=tree[p].next[id]; tree[p].c[0]++; if(tree[p].loc<dex){ tree[p].c[1]++; tree[p].loc=i; } i++; } } int query(){ int temp=root,i=0; while(keyword[i]){ int t=keyword[i]-97; if(tree[temp].next[t]==-1)return 0; temp=tree[temp].next[t]; i++; } return tree[temp].c[tp]; } int main(){ //freopen("cin.txt","r",stdin); int cas=1; while(~scanf("%s",str)){ top=0; root=newnode(); int length=strlen(str); for(int i=0;i<length;i++){ //here insert_t(i); } scanf("%d",&N); printf("Case %d\n",cas++); for(int i=0;i<N;i++){ scanf("%d%s",&tp,keyword); printf("%d\n",query()); } puts(""); } return 0; }代码中的here: 用length存储strlen的结果,不然在循环中反复计算就超时了。(自己当时就犯这种错误)
#include <iostream> #include<cstdio> #include<cstring> #include <queue> using namespace std; const int nn=26,maxn=1e5+10; char str[maxn],word[15]; struct node{ int pos,len,id[2]; node *next[27],*fail; node(){ pos=-1; id[0]=id[1]=len=0; fail=NULL; memset(next,0,sizeof(next)); } }; node *root,*que[maxn*6]; int *question[maxn]; //因为要保存值,所以要设成指针数组. 指针只读不写! void insert(char *s,int tag,int dex){ node *p=root; int length=strlen(s); for(int i=0;i<length;i++){ if(p->next[s[i]-'a']==0) p->next[s[i]-'a']=new node(); p=p->next[s[i]-'a']; } p->len=length; question[dex]=&(p->id[tag]); } void build_fail(){ int head=0,tail=0; que[tail++]=root; while(head<tail){ node *p=que[head++],*temp=NULL; for(int i=0;i<nn;i++){ if(p->next[i]){ node *f=p->fail; while(f){ if(f->next[i]){ p->next[i]->fail=f->next[i]; //对应图 break; } f=f->fail; } if(f==root)f->next[i]->fail=root; que[tail++]=p->next[i]; } } } } void find(char *s){ //fail指针,KMP都是紧密相连的 int length=strlen(s); node *p=root; for(int i=0;i<length;i++){ int k=s[i]-'a'; while(p->next[k]==NULL&&p!=root)p=p->fail; /*p=p->next[k]; //this sentence is wrong, it make program stop ******************* if(!p)p=root; //调整目标串的对应起点 node *tmp=p; while(tmp!=root){ //回到根节点说明就已经把能找的都找完了,如果一开始tmp就等于root,那么起点就是长串的第一个字符,顺推~ if(tmp->len>0){ tmp->id[0]++; if(tmp->pos==-1 || i-tmp->pos>=tmp->len){ //i-tmp->pos>=tmp->len not > tmp->id[1]++; tmp->pos=i; //更新 } } tmp=tmp->fail; }*/ } } void del(node *p){ if(p==NULL)return ; for(int i=0;i<nn;i++)del(p->next[i]); delete p; } int main() { freopen("cin.txt","r",stdin); int ca=1; while(cin>>str){ root=new node(); int n,tag; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d%s",&tag,word); insert(word,tag,i); } build_fail(); node *p=root; cout<<str<<endl; find(str); printf("Case %d\n",ca++); cout<<*question[0]<<endl; for(int i=0;i<n;i++){ printf("%d\n",*question[i]); } puts(""); del(root); } return 0; }
错误:0x3C0000005
----------------------------------------------------------------------------------------------------------------------------------------
2016. 03 .31
插入的思想都不一样,当然出现各种错误了。应该是把长串上的各个连续子串都放进trie树。