• bzoj 1195 [HNOI2006]最短母串 bfs 状压 最短路 AC自动机


    LINK:最短母串

    求母串的问题。不适合SAM。

    可以先简化问题 考虑给出的n个字符串不存在包含关系。

    那么 那么存在的情况 只可能有 两个字符串拼接起来能表示另外一个字符串 或者某个字符串的后缀可以当成别的字符串的前缀使用。

    实际情况可能更加复杂。

    观察上面的两种情况 容易AC自动机可以解决类似的问题。

    在AC自动机上跑 就可以借用别的字符串的后缀当做自己的前缀进行使用了。

    考虑建立出AC自动机 我们要求出一条路径 使得AC自动机上所有的终止节点都被经过。

    当然也有特殊情况 就是 以终止节点为fail的节点 或者 以这个节点为fail的节点被经过。

    考虑如何求出最短的路径。

    可以发现这是一个最短路的问题。当做分层图来跑最短路。

    对于上述的两种情况 由于是在 AC自动机的trie图上跑 所以可以满足。

    考虑字典序 每次选择节点从字典序最小的选即可。

    注意要预处理出s[x]数组 表示x这个节点所表示的所有终止节点的集合 注意 fail指针的s可以传递过来。

    const int MAXN=610,maxn=1<<12;
    int n,cnt,maxx;
    char a[13][MAXN],b[MAXN],ans[MAXN];
    int s[MAXN],q[1500010],vis[MAXN][maxn],pre[MAXN][maxn],w[1500010];
    struct wy{int ch[26];int fail;}t[MAXN];
    
    inline void insert(int x)
    {
    	int len=strlen(a[x]+1);
    	int p=0;
    	rep(1,len,i)
    	{
    		int w=a[x][i]-'A';
    		if(!t[p].ch[w])t[p].ch[w]=++cnt;
    		p=t[p].ch[w];b[p]=a[x][i];
    	}
    	s[p]=s[p]|(1<<(x-1));
    }
    
    inline void get_fail()
    {
    	int l=0,r=0;
    	rep(0,25,i)if(t[0].ch[i])q[++r]=t[0].ch[i];
    	while(++l<=r)
    	{
    		int x=q[l];
    		rep(0,25,i)
    		{
    			int tn=t[x].ch[i];
    			if(tn)fail(tn)=t[fail(x)].ch[i],s[tn]|=s[t[fail(x)].ch[i]],q[++r]=tn;
    			else t[x].ch[i]=t[fail(x)].ch[i];
    		}
    	}
    }
    
    inline void bfs()
    {
    	int l=0,r=0;q[++r]=0;
    	vis[0][0]=0;w[r]=0;
    	while(++l<=r)
    	{
    		int x=q[l];
    		int xx=w[l];
    		rep(0,25,i)
    		{
    			int tn=t[x].ch[i];
    			if(tn)
    			{
    				int ss=s[tn]|xx;
    				if(vis[tn][ss]==-1)
    				{
    					pre[tn][ss]=l;
    					vis[tn][ss]=vis[x][xx]+1;
    					q[++r]=tn;w[r]=ss;
    					if(ss==maxx)
    					{
    						int w1=tn,w2=ss;
    						while(vis[tn][ss])
    						{
    							ans[vis[tn][ss]]=b[w1];
    							--vis[tn][ss];
    							int s1=q[pre[w1][w2]];
    							int s2=w[pre[w1][w2]];
    							w1=s1;w2=s2;
    						}
    						printf("%s",ans+1);
    						return;
    					}
    				}
    			}
    		}
    	}
    }
    
    int main()
    {
    	freopen("1.in","r",stdin);
    	gt(n);maxx=(1<<n)-1;
    	rep(1,n,i)gc(a[i]),insert(i);
    	get_fail();
    	memset(vis,-1,sizeof(vis));
    	bfs();return 0;
    }
    
  • 相关阅读:
    pycharm运行Django项目,提示UnicodeDecodeError: 'gbk' codec can't decode byte 0xa6
    linux环境下 python环境import找不到自定义的模块
    python-获取URL中的json数据
    python-Excel读取-合并单元格读取
    自动驾驶控制算法第七讲 离散规划轨迹的误差计算
    静态语言和动态语言的区别
    Python函数-导入模块的顺序及原理
    使用Visual Studio查看C++类内存分布
    在VisualStudio调试器中使用内存窗口和查看内存分布
    visual studio 2019工具里添加开发中命令提示符的方法
  • 原文地址:https://www.cnblogs.com/chdy/p/12723043.html
Copyright © 2020-2023  润新知