这题目郁闷死了,因为一些小错误,搞了半天,不过,要注意的东西真的很多哦
题意是找出单词的所有符号要求的匹配模式,首先将模式存入字典树中,再用单词进行查找
需要注意的问题:看到输出的sample也应该知道了,一个单词有多种匹配模式,用一个单词进行遍历时,到达同一个单词的结尾,却可能经历了不同的匹配模式,所以这里用了并查集来保存
具体的,还是结合代码吧,比较好解释
#include<iostream> #include<string> #include<algorithm> using namespace std; struct node { int num;//保存模式的编号 node *next[28]; }; node *root; int cou[400005],f[100005],len,k;//cou记录所有的匹配模式,f记录到达同一个节点的模式的编号,将这些模式关联起来 char key[10],str[25]; void insert(char *s,int d)//插入过程基本和之前没什么区别,就是多了俩个指针 { node *p=root; for(;*s!='\0';s++) { if(*s>='a'&&*s<='z') { int id=*s-'a'; if(p->next[id]!=NULL) { p=p->next[id]; } else { p->next[id]=new node(); p->next[id]->num=-1; p=p->next[id]; } } else if(*s=='?') { if(p->next[26]!=NULL) { p=p->next[26]; } else { p->next[26]=new node(); p->next[26]->num=-1; p=p->next[26]; } } else { if(p->next[27]!=NULL) p=p->next[27]; else { p->next[27]=new node(); p->next[27]->num=-1; p=p->next[27]; } } } if(p->num==-1) p->num=d; else //出现相同的模式,用并查集将编号关联起来 { f[d]=p->num; p->num=d; } } void dfs(node *p,int d) { if(str[d]==0)//所查的单词到达末尾 { if(p->num!=-1)//存在匹配的模式 { k++; cou[k]=p->num; } while(p->next[27]!=NULL)//以“*”结尾的模式十分特殊,因为“*”既可以表示一个,多个,也可以表示没有,所有一直查找后面是否还有以*号结尾的模式 { if(p->next[27]->num!=-1) { k++; cou[k]=p->next[27]->num; } p=p->next[27]; } return ; } if(p->next[str[d]-'a']!=NULL) dfs(p->next[str[d]-'a'],d+1); if(p->next[26]!=NULL)//只要是存在“?",都可以进入搜索 dfs(p->next[26],d+1); if(p->next[27]!=NULL)//*号还是比较麻烦 { for(int i=d;i<=len;i++)//这里i从d开始,包含了三种情况,*号表示为空,一个,还有多个,用DFS原来如此巧妙呀, //而且很好理解,注意,这里的i<=len,'='号不能省呀,注意深搜的退出条件 dfs(p->next[27],i); } } int main() { int i,j,ans,n,m; while(scanf("%d %d",&n,&m)!=EOF) { for(i=0;i<n;i++) f[i]=i; root=new node(); root->num=-1; for(i=0;i<n;i++) { scanf("%s",key); insert(key,i); } while(m--) { scanf("%s",str); len=strlen(str); k=0; dfs(root,0); if(k==0)//一个都没找到 { printf("No match\n"); } else { ans=k; for(i=1;i<=ans;i++) { j=cou[i]; while(f[j]!=j)//找出与该模式关联的模式,存入cou中 { k++; cou[k]=f[j]; j=f[j]; } } sort(cou+1,cou+k+1);//悲剧就在这里了,k忘记加一了,可是测试例子居然没错呀 cou[0]=-1; for(i=1;i<=k;i++) { if(cou[i]!=cou[i-1])//注意不要输出相同的 printf("%d ",cou[i]);//最后一个输出多了一个空格,但还是A 了,省了不少麻烦 } printf("\n"); } } } return 0; }