• bzoj 3790 神奇项链 回文串 manacher|PAM


    LINK:神奇项链

    存在两个操作:1. 一个操作可以生成所有形式的回文串 2.一个操作可以将两个串给合并起来 如果前缀和后缀相同还可以将其并起来。

    多组询问 每次询问合成一个串所需最少多少次2操作。

    不考虑1操作 那么我们可以把所有需要的串都给生成出来 对于原字符串没有贡献的当然是不需要的了。

    可以发现 当原字符串有一部分不是回文但是前一部分和后一部分用的同一个地方都成为了回文 此时也是可以进行2操作的。

    考虑从前往后构造当前面一部分构造好了后面无论占用前面多大位置都没有问题。

    转换成区间覆盖问题。问题是我们要覆盖区间的线段怎么找。原串中的回文串。

    可以发现越大越好 对于每个点找到最长的回文串进行区间覆盖问题即可。

    PAM解决(忘了 Manacher解决吧。

    求出区间之后 可以排序+贪心解决。

    当然 可以考虑求出以某个节点为左端的的最长右端点这个复杂度为O(n)也就自然省掉了排序的过程+贪心可以达到O(n).

    也可以暴力求出所有区间然后排序。

    最后的贪心:可以dp来做 但是需要数据结构优化一下 直接贪心考虑左端点一定往后延伸最长右端点。

    const int MAXN=50010;
    int n,cnt,id;
    int p[MAXN<<1];
    char a[MAXN],b[MAXN<<1];
    struct wy
    {
    	int x,y;
    	inline int friend operator <(wy a,wy b){return a.x<b.x;}
    }t[MAXN<<1];
    inline void manacher()
    {
    	int mx=0,mid=0;
    	rep(1,cnt,i)
    	{
    		if(i<mx)p[i]=min(p[(mid<<1)-i],mx-i);
    		else p[i]=1;
    		while(b[i-p[i]]==b[i+p[i]])++p[i];
    		if(p[i]+i>mx)mx=p[i]+i,mid=i;
    	}
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	while(~gc(a))
    	{
    		n=strlen(a+1);id=0;
    		b[0]='&';b[cnt=1]='#';
    		rep(1,n,i)b[++cnt]=a[i],b[++cnt]='#';
    		manacher();
    		for(int i=2,j=0;i<=cnt;++i)
    		{
    			int ww=p[i]-1;
    			if(ww)
    			{
    				if(i&1)t[++id]=(wy){j-ww/2+1,j+ww/2};
    				else ++j,t[++id]=(wy){j-ww/2,j+ww/2};
    			}
    		}
    		sort(t+1,t+1+id);
    		int L=0,flag=1,ans=-1;
    		while(L<n)
    		{
    			int mx=0;
    			while(t[flag].x<=L+1&&flag<=id)mx=max(t[flag].y,mx),++flag;
    			L=mx;++ans;
    		}
    		put(ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    asp.net跳转页面的三种方法比较
    DotNet软件开发框架
    asp.net在ie7中使用FileUpload上传前预览图片
    uv贴图详解
    3d之 panda3d
    3dmax9中文版注册机
    flash player本地安全设置
    处理2D图像和纹理——扩展图像内容处理器
    处理2D图像和纹理——扩展图像内容处理器:灰度变换和处理器参数
    处理2D图像和纹理——将场景绘制到纹理
  • 原文地址:https://www.cnblogs.com/chdy/p/12637758.html
Copyright © 2020-2023  润新知