• pku1816 Wild Words(字典树+DFS+并查集)


    这题目郁闷死了,因为一些小错误,搞了半天,不过,要注意的东西真的很多哦

    题意是找出单词的所有符号要求的匹配模式,首先将模式存入字典树中,再用单词进行查找

    需要注意的问题:看到输出的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;
    }
    
  • 相关阅读:
    Vuejs使用笔记 --- component内部实现
    Vuejs使用笔记 --- 框架
    jQuery学习笔记(控件位置定位、尺寸大小的获取等)
    jQuery学习笔记(在js中增加、删除及定位控件的操作)
    jQuery 学习笔记(函数调用机制)
    Kernel Summit 2013会议记录
    2013 CLSF会议记录
    Android开发环境配置
    请问一下这三种存储方法的区别?原理是什么样子的?哪一种比较好,能不能提供一些意见。谢谢
    UIScrollViewDelegate
  • 原文地址:https://www.cnblogs.com/nanke/p/2047887.html
Copyright © 2020-2023  润新知