zoukankan      html  css  js  c++  java
  • 【BZOJ4560】[JLoi2016]字符串覆盖 KMP+状压DP

    【BZOJ4560】[JLoi2016]字符串覆盖

    Description

    字符串A有N个子串B1,B2,…,Bn。如果将这n个子串分别放在恰好一个它在A中出现的位置上(子串之间可以重叠)这样A中的若干字符就被这N个子串覆盖了。问A中能被覆盖字符个数的最小值和最大值。

    Input

    第一行包含一个正整数T,表示数据组数。保证T≤10。接下来依次描述T组数据,每组数据中:第一行包含一个由小写字母组成的字符串,表示母串A。第二行包含一个整数N,表示子串的个数。接下来N行,每行包含一个由小写字母组成的字符串,描述子串。数据保证所有子串均在母串中出现。字符串长度A<=10000,N<=4,子串长充<=1000

    Output

    输出为T行,对应每组数据的答案。每行包含两个整数Minans和Maxans,分别表示对应数据中能被覆盖字符数量的最小值和最大值。

    Sample Input

    2
    hello
    4
    he
    l
    l
    o
    abacaba
    4
    ab
    ba
    a
    c

    Sample Output

    4 5
    4 6

    题解:网上题解说是某贪心?然而我只会状压DP。

    先用KMP求出每个子串的所有出现位置,然后用f[i][j]表示前i个字符,子串的出现情况为j的覆盖数量最大值,g[i][j]表示最小值。转移时需要用到树状数组。

    然而状压的做法似乎好多情况都无法处理,如子串存在包含的情况。。。总之加了一坨特判就过了,可能会被hack。

    代码不可读。

     

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define lson x<<1
    #define rson x<<1|1
    using namespace std;
    const int maxn=10010;
    int n,m;
    int len[5],vis[5],ch[maxn],next[maxn];
    char S[maxn],T[5][maxn];
    int f[maxn][16],g[maxn][16],sf[maxn][16],sg[maxn][16];
    struct node
    {
    	int s[maxn],typ;
    	inline int cmp(int a,int b)
    	{
    		return ((a>b)^typ)?a:b;
    	}
    	inline void updata(int x,int v)
    	{
    		x++;
    		for(int i=x;i;i-=i&-i)	s[i]=cmp(s[i],v);
    	}
    	inline int query(int x)
    	{
    		x++;
    		int i,ret=s[0];
    		for(i=x;i<=m+1;i+=i&-i)	ret=cmp(ret,s[i]);
    		return ret;
    	}
    }s1[16],s2[16];
    void work()
    {
    	scanf("%s",S),m=strlen(S);
    	scanf("%d",&n);
    	int i,j,k,a,b,tmp=(1<<n)-1;
    	memset(ch,0,sizeof(ch));
    	for(i=1;i<=n;i++)
    	{
    		memset(next,0,sizeof(next));
    		scanf("%s",T[i]),len[i]=strlen(T[i]);
    		next[0]=k=-1,j=0;
    		while(j<len[i])
    		{
    			if(k==-1||T[i][j]==T[i][k])	next[++j]=++k;
    			else	k=next[k];
    		}
    		j=k=0;
    		while(j<m)
    		{
    			if(k==-1||S[j]==T[i][k])	j++,k++;
    			else	k=next[k];
    			if(k==len[i])	ch[j-len[i]]|=1<<(i-1);
    		}
    	}
    	memset(vis,0,sizeof(vis));
    	for(a=1;a<=n;a++)	for(b=1;b<=n;b++)	if(a!=b&&!vis[a]&&!vis[b])
    	{
    		memset(next,0,sizeof(next));
    		next[0]=k=-1,j=0;
    		while(j<len[a])
    		{
    			if(k==-1||T[a][j]==T[a][k])	next[++j]=++k;
    			else	k=next[k];
    		}
    		j=k=0;
    		while(j<len[b])
    		{
    			if(k==-1||T[b][j]==T[a][k])	j++,k++;
    			else	k=next[k];
    			if(k==len[a])
    			{
    				vis[a]=1;
    				break;
    			}
    		}
    	}
    	for(i=1;i<=n;i++)	if(vis[i])	tmp^=1<<(i-1);
    	memset(s1,0xc0,sizeof(s1)),memset(s2,0x3f,sizeof(s2));
    	memset(sf,0xc0,sizeof(sf)),memset(sg,0x3f,sizeof(sg));
    	memset(f,0xc0,sizeof(f)),memset(g,0x3f,sizeof(g));
    	for(i=0;i<1<<n;i++)	s1[i].typ=0,s2[i].typ=1,f[0][i]=-1<<30,g[0][i]=1<<30;
    	for(i=0;i<=m;i++)
    	{
    		for(j=0;j<1<<n;j++)
    		{
    			if(!i)
    			{
    				if(!j)	f[0][0]=g[0][0]=sf[0][0]=sg[0][0]=0;
    				else	f[0][j]=s1[j].query(i)+i,g[0][j]=s2[j].query(i)+i;
    			}
    			else
    			{
    				sf[i][j]=max(sf[i][j],sf[i-1][j]),sg[i][j]=min(sg[i][j],sg[i-1][j]);
    				f[i][j]=max(sf[i][j],s1[j].query(i)+i),g[i][j]=min(sg[i][j],s2[j].query(i)+i);
    			}
    			for(k=1;k<=n;k++)	if(!((j>>(k-1))&1)&&((ch[i]>>(k-1))&1))
    			{
    				s1[j|(1<<(k-1))].updata(i+len[k],f[i][j]-i);
    				sf[i+len[k]][j|(1<<(k-1))]=max(sf[i+len[k]][j|(1<<(k-1))],f[i][j]+len[k]);
    				if(!vis[k])
    				{
    					s2[j|(1<<(k-1))].updata(i+len[k],g[i][j]-i);
    					sg[i+len[k]][j|(1<<(k-1))]=min(sg[i+len[k]][j|(1<<(k-1))],g[i][j]+len[k]);
    				}
    			}
    		}
    	}
    	int ans=0;
    	for(i=1;i<1<<n;i++)	if((i&tmp)==tmp)	ans=max(ans,f[m][i]);
    	printf("%d %d
    ",g[m][tmp],ans);
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)	work();
    	return 0;
    }//2 hello 4 he l l o abacaba 4 ab ba a c 

     

     
  • 相关阅读:
    element-ui的table表格控件表头与内容列不对齐问题
    uniapp 调用手机相机拍照实现图片上传
    配置Git忽略文件
    【转载】Java的几种常见排序算法
    httpclient封装
    idea 启动springboot项目时报错:org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource
    shell脚本监控网站,异常则进行邮件报警
    nginx配置图片跨域访问
    Nginx基于多端口、多域名配置
    docker部署Nginx项目dockerfile
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7670985.html
Copyright © 2011-2022 走看看