zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    JVM类加载的过程
    接口文档设计
    代码规范及CodeReview要点
    Linux权限
    Linux文件
    UltraEdit编辑器基础技巧
    Android环境配置
    JDK 环境配置
    xml没有提示解决办法<eclipse>
    mysql事务实例
  • 原文地址:https://www.cnblogs.com/chdy/p/12723043.html
Copyright © 2011-2022 走看看