此题解无病呻吟,啰里啰嗦,现已加入零分作文全家桶

这题......坑死我了......

不妨记原串长为i的前缀为prefix(i),next[i]表示prefix(i)的最长公共前后缀长度(不等于prefix(i)自身)(就是MP的next[])

首先,一个前缀必须同时也是原串的后缀才有可能成为答案,否则原串的最后一部分无法覆盖。

所以我们沿着next表往前走,可以找出原串的所有公共前后缀,筛选出可能的答案。

接下来我们验证每个可能的答案。如果用prefix(i)作为模板串,我们可以用KMP算法直接找出prefix(i)在原串中所有的出现位置,这些位置就是prefix(i)可以涂到的位置。接下来把能涂上模板的位置都涂上,判断能否覆盖整个字符串。这相当于找出相邻两个能够涂上模板的位置的最大间隔,看一下这个间隔长度和prefix(i)的长度哪一个大,如果最大间隔比prefix(i)长就说明不能覆盖。

这样暴力做是O(n^2)的。本脑子有坑选手考试连O(n^2)都没推出来,打的O(n^2logn)的->_->

接下来好多人都假定“prefix(i),prefix(j)是两个公共前后缀,i<j,如果prefix(i)是一个可行解,那么prefix(j)一定是可行解,如果prefix(j)不是可行解,那么prefix(i)一定不是可行解”,于是二分答案。但这个题其实没有单调性。比如这个数据:

aabccaabccaabcaabccaabcaabccaabccaabccaabccaabccaabcaabccaabc

prefix(9)是可行解,但prefix(23)不是可行解.....所以二分答案是错的,也可以构造数据卡掉,然而bzoj上好多二分答案过掉的->_->

考虑两个可能的答案prefix(j)和prefix(i),j<i.原串中的某个位置如果能够匹配上prefix(i),那么这个位置一定也能够匹配上prefix(j),但匹配上prefix(j)不一定能够匹配上prefix(i),这启发我们可以按照一定的顺序枚举可能的答案,同时维护所有相邻匹配点的最大间隔。既然题中求的是最小的长度,我们不妨从短到长枚举答案,此时匹配点不断减少。

问题变成:如何快速找出从较短答案变为一个较长答案时减少的匹配点,如何快速完成匹配点的删除并维护最大间隔。

第二个问题,我们可以用一个只带删除操作的链表维护所有匹配点。

这个链表由于只有删除,可以直接用数组实现,pre[i]表示如果点i是匹配点,前一个匹配点是谁;suc[i]表示如果点i是匹配点,下一个匹配点是谁。那么删除i的时候我们用(suc[i]-pre[i])更新最大间隔,并维护suc[]和pre[]数组即可。

第一个问题则需要用到fail树。对1<=i<=n,我们连一条从next[i]到i的边,根节点为0,形成一棵fail树,树中的每个节点i其实代表了原串的一个前缀prefix(i)。fail树中节点i到根节点的路径上包含了prefix(i)的所有公共前后缀。记fail树中以i为根的子树为subtree(i)

fail树的一个性质是:prefix(i)在原串中所有的出现位置(以prefix(i)出现时最后一个字符的下标表示出现位置)都在subtree(i)中

如果prefix(i)的一个出现位置是k,那么prefix(i)就是prefix(k)的后缀,也就是说prefix(i)是prefix(k)的公共前后缀,因此i在k到根节点的路径上,故k在subtree(i)中。

如果k在subtree(i)中,那么i就在k到根节点的路径上,因此prefix(i)是prefix(k)的公共前后缀,故prefix(i)的一个出现位置是k

然后我们发现,从短到长枚举所有可能答案的过程其实是在fail树上从树根朝着节点n走,当前验证节点i时所有可能的匹配点就是subtree(i)中的点,减少的匹配点一定不在subtree(i)中却在subtree(i的父亲)中。因此每走一步我们就用bfs找出subtree(i的父亲)中不属于subtree(i)的点,将它们从链表中删掉即可。

#include<cstdio>

#include<cstring>

const int maxn=;

char str[maxn];

int next[maxn];

int getnext(){

    int i=,j=;next[]=next[]=;

    for(;str[i]!='\0';++i){

        while(j&&str[i]!=str[j])j=next[j];

        if(str[i]==str[j])++j;

        next[i+]=j;

    }

    return i;

}

int pre[maxn],suc[maxn];

struct edge{

    int to,next;

}lst[maxn];int len=;

int first[maxn];

void addedge(int a,int b){

    lst[len].to=b;

    lst[len].next=first[a];

    first[a]=len++;

}

int maybe[maxn],tot=;

int maxgap=;

void del(int x){

    if(suc[x])pre[suc[x]]=pre[x];

    if(pre[x])suc[pre[x]]=suc[x];

    if(pre[x]!=&&suc[x]!=&&suc[x]-pre[x]>maxgap)maxgap=suc[x]-pre[x];

    pre[x]=suc[x]=;

};

int q[maxn],head,tail;

void bfs(int s,int avoid){

    head=tail=;

    q[tail++]=s;

    while(head!=tail){

        int x=q[head++];

        if(x==avoid)continue;

        del(x);

        for(int pt=first[x];pt;pt=lst[pt].next){

            q[tail++]=lst[pt].to;

        }

    }

}

int main(){

    scanf("%s",str);

    int n=getnext();

    for(int i=;i<=n;++i){

        addedge(next[i],i);

    }

    for(int i=n;i;i=next[i])maybe[++tot]=i;

    for(int i=;i<=n;++i){

        pre[i]=i-;   

        suc[i]=i+;

    }

    suc[n]=;

    for(int i=tot;i>=;--i){

        bfs(maybe[i+],maybe[i]);

        if(maxgap<=maybe[i]){

            printf("%d\n",maybe[i]);

            break;

        }

    }

    return ;

}

bzoj1535[POI2005]sza-template的更多相关文章

  1. 为.NET Core项目定义Item Template

    作为这个星球上最强大的IDE,Visual Studio不仅仅提供了很多原生的特性,更重要的是它是一个可定制的IDE,比如自定义Project Template和Item Template就是一个非常 ...

  2. jQuery.template.js 简单使用

    之前看了一篇文章<我们为什么要尝试前后端分离>,深有同感,并有了下面的评论: 我最近也和前端同事在讨论这个问题,比如有时候前端写好页面给后端了,然后后端把这些页面拆分成很多的 views, ...

  3. 2000条你应知的WPF小姿势 基础篇<69-73 WPF Freeze机制和Template>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000ThingsYou Should Know About C# 和 2,00 ...

  4. tornado template

    若果使用Tornado进行web开发可能会用到模板功能,页面继承,嵌套... 多页应用模板的处理多半依赖后端(SPA就可以动态加载局部视图),就算是RESTfull的API设计,也不妨碍同时提供部分模 ...

  5. 设计模式(九): 从醋溜土豆丝和清炒苦瓜中来学习"模板方法模式"(Template Method Pattern)

    今天是五.四青年节,祝大家节日快乐.看着今天这标题就有食欲,夏天到了,醋溜土豆丝和清炒苦瓜适合夏天吃,好吃不上火.这两道菜大部分人都应该吃过,特别是醋溜土豆丝,作为“鲁菜”的代表作之一更是为大众所熟知 ...

  6. C++泛型编程:template模板

    泛型编程就是以独立于任何特定类型的方式编写代码,而模板是C++泛型编程的基础. 所谓template,是针对“一个或多个尚未明确的类型”所编写的函数或类. 使用template时,可以显示的或隐示的将 ...

  7. 新手入门Underscore.js 中文(template)

    Underscore.js是一个很精干的库,压缩后只有4KB.它提供了几十种函数式编程的方法,弥补了标准库的不足,大大方便了javaScript的编程.MVC框架Backbone.js就将这个库作为自 ...

  8. knockoutjs如何动态加载外部的file作为component中的template数据源

    玩过knockoutjs的都知道,有一个强大的功能叫做component,而这个component有个牛逼的地方就是拥有自己的viewmodel和template, 比如下面这样: ko.compon ...

  9. JavaScript模板引擎artTemplate.js——template.helper()方法

    上一篇文章我们已经讲到了helper()方法,但是上面的例子只是一个参数的写法,如果是多个参数,写法就另有区别了. <div id="user_info"></d ...

随机推荐

  1. IE6/IE7/IE8/Firefox/Chrome/Safari的CSS hack兼容一览表

    浏览器兼容问题一直是前段开发工程师比较头痛的问题,熟悉了里面的规则也就变得简单了,这里有一份资料可以分享给大家,大家平时开发过程中遵循这个规律的话,会变得轻松多了: 各浏览器CSS hack兼容表: ...

  2. MYSQL查询优化

    目前手头有个查询: SELECT LPP.learning_project_pupilID, SL.serviceID, MAX(LPPO.start_date), SUM(LPPOT.license ...

  3. 细细品味Storm_Storm简介及安装

    Storm是由专业数据分析公司BackType开发的一个分布式实时数据处理软件,可以简单.高效.可靠地处理大量的数据流.Twitter在2011年7月收购该公司,并于2011年9月底正式将Storm项 ...

  4. CSS 颜色代码大全

    CSS颜色: 转载:http://www.cnblogs.com/axing/archive/2011/04/09/CSS.html

  5. checkboxlist 下拉框多选功能 ,模拟dropdownlist带复选框效果

    前台代码 01.<html xmlns="http://www.w3.org/1999/xhtml"> 02.<head runat="server&q ...

  6. Dockerfile创建自定义Docker镜像以及CMD与ENTRYPOINT指令的比较

    1.概述 创建Docker镜像的方式有三种 docker commit命令:由容器生成镜像: Dockerfile文件+docker build命令: 从本地文件系统导入:OpenVZ的模板. 关于这 ...

  7. Mysql之case语句(附带实例)

    这段时间,做项目做累了,好不容易有点个人的学习时间,利用这个小时,总结一下,最近做统计的时候常用的case语句吧. 结构:case  when… then …end 1.判断的同时改变其值 eg:   ...

  8. swfupload提示“错误302”的解决方法

    1.关于图片上传控件,flash控件的显示效果要好一些,本人使用swfupload 2.swfupload上传控件使用方式详见文档 http://www.leeon.me/upload/other/s ...

  9. 记一次在Eclipse中用Axis生成webservice服务端的过程中出现的问题

    问题一. Unable to find config file.  Creating new servlet engine config file: /WEB-INF/server-config.ws ...

  10. 富文本KidnEditor在MVC中的应用

    最近看到很多网站后台都用到了富文本,包括自己所在的公司也是.公司用的KindEditor,所以就讲讲KindEditor.之前我也没学过,所以网上搜了一篇博文,直接转载如下(PS:完全以学习为目的哦~ ...