题目: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的结果,不然在循环中反复计算就超时了。(自己当时就犯这种错误)
本来也想用AC解决的,结果中间有一个错误不理解也改不了。。。贴上来,说不定哪天自己就看出来了:
#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树。