Description

母亲节就要到了,小 H 准备送给她一个特殊的项链。这个项链可以看作一个用小写字母组成的字符串,每个小写字母表示一种颜色。
为了制作这个项链,小 H 购买了两个机器。第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。例如:aba和aca连接起来,可以生成串abaaca或 abaca。
现在给出目标项链的样式,询问你需要使用第二个机器多少次才能生成这个特殊的项链。 

Input

输入数据有多行,每行一个字符串,表示目标项链的样式。 

Output

多行,每行一个答案表示最少需要使用第二个机器的次数。 

Sample Input

abcdcba
abacada
abcdef

Sample Output

0
2
5

HINT

每个测试数据,输入不超过 5行,每行的字符串长度小于等于 50000。
 
 
分析:
        回文串之间可以相互重叠,但是不妨碍辨认这些回文串,因此问题就变成了在给出的字符串中找到数量最少的回文串覆盖整个字符串。一个字符串看成一条线段,经典的贪心问题,只需要再求出每个点为中心的最长回文串即可进行贪心(如果不用回文树的话小技巧是在字符串的间隔插上一个分隔符)。
        最后用了二分+hash来求这个东西,想了想还可以用回文自动机把串倒着插进去来进行贪心。(bzoj不能用gets真的是太可怕了)
        于是我把两份代码都拿出来了(滑稽) 
 
 hash:
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
using namespace std;
const int maxn=;
typedef long long LL;
const int mo=; char S[maxn],T[maxn];
int n,hash1[maxn],hash2[maxn],pw[maxn];
struct data{ int l,r; }line[maxn]; bool check(int i,int mid)
{
int v1=i-mid==?hash1[i]:(hash1[i]-1ll*hash1[i-mid-]*pw[mid+]%mo+mo)%mo;
int v2=i+mid==n-?hash2[i]:(hash2[i]-1ll*hash2[i+mid+]*pw[mid+]%mo+mo)%mo;
return v1==v2;
}
bool cmp(data x,data y){ return x.l<y.l||x.l==y.l&&x.r<y.r; }
void work()
{
n=strlen(T);
hash1[]=T[]-'A'+;
for(int i=;i<n;i++) hash1[i]=(hash1[i-]*89ll+T[i]-'A'+)%mo;
hash2[n-]=T[n-]-'A'+;
for(int i=n-;i>=;i--) hash2[i]=(hash2[i+]*89ll+T[i]-'A'+)%mo;
for(int i=;i<n;i++){
int L=,R=min(i,n-i-)+,mid,len=;
while(L<R){
mid=L+R>>;
if(check(i,mid)) len=mid,L=mid+;
else R=mid;
}
line[i]=(data){i-len,i+len};
}
sort(line,line+n,cmp);
int ans=,pos=,mx=;
for(int i=;i<n;i++){
if(line[i].l>pos) pos=mx,mx=,ans++;
if(line[i].r>mx) mx=line[i].r;
}
printf("%d\n",max(,ans-));
}
int main()
{
pw[]=;
for(int i=;i<=;i++) pw[i]=pw[i-]*89ll%mo;
while(scanf("%s",S)==){
int cnt=; n=strlen(S);
T[cnt++]='A';
for(int i=;i<n;i++)
T[cnt++]=S[i],T[cnt++]='A';
T[cnt]='\0';
work();
}
return ;
}

回文自动机:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
#include<ctime>
using namespace std;
const int maxl=; char S[maxl];
int r[maxl];
struct PAM{
static const int maxn=;
int sz,last,to[maxn][],len[maxn],fail[maxn],s[maxn],n;
int newnode(int l){
memset(to[sz],,sizeof(to[sz]));
len[sz]=l,fail[sz]=;
return sz++;
}
void init(){
sz=last=n=;
newnode();newnode(-);
s[]=-,fail[]=;
}
int getfail(int p){
while(s[n]!=s[n-len[p]-]) p=fail[p];
return p;
}
void extend(int w){
s[++n]=w;
int p=getfail(last);
if(!to[p][w]){
int np=newnode(len[p]+);
fail[np]=to[getfail(fail[p])][w];
to[p][w]=np;
}
last=to[p][w];
}
}pam; int main()
{
while(scanf("%s",&S)==){
pam.init();
int n=strlen(S);
for(int i=n-;i>=;i--){
pam.extend(S[i]-'a');
r[i]=i+pam.len[pam.last];
}
int pos=,mx=,ans=;
for(int i=;i<n;i++){
if(i>pos) pos=mx,mx=,ans++;
if(r[i]>mx) mx=r[i];
if(i==n-&&pos==n-) ans++;
}
printf("%d\n",max(,ans-));
}
return ;
}

BZOJ 3790 神奇项链 hash/后缀自动机+贪心的更多相关文章

  1. BZOJ 3790 神奇项链(manacher+贪心)

    3790: 神奇项链 Time Limit: 10 Sec  Memory Limit: 64 MB Description 母亲节就要到了,小 H 准备送给她一个特殊的项链.这个项链可以看作一个用小 ...

  2. BZOJ 3790: 神奇项链 [Manacher 贪心]

    3790: 神奇项链 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 405  Solved: 200[Submit][Status][Discuss] ...

  3. bzoj 3790: 神奇项链

    3790: 神奇项链 Description 母亲节就要到了,小 H 准备送给她一个特殊的项链.这个项链可以看作一个用小写字 母组成的字符串,每个小写字母表示一种颜色.为了制作这个项链,小 H 购买了 ...

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

    LINK:神奇项链 存在两个操作:1. 一个操作可以生成所有形式的回文串 2.一个操作可以将两个串给合并起来 如果前缀和后缀相同还可以将其并起来. 多组询问 每次询问合成一个串所需最少多少次2操作. ...

  5. BZOJ 3790 神奇项链(回文自动机+线段树优化DP)

    我们预处理出来以i为结尾的最长回文后缀(回文自动机的构建过程中就可以求出)然后就是一个区间覆盖,因为我懒得写贪心,就写了线段树优化的DP. #include<iostream> #incl ...

  6. bzoj 3790 神奇项链(Manacher,DP+BIT | 贪心)

    [题意] 你可以产生一个回文串,也可以将两个串合并成一个串,问产生目标串需要的最少合并次数. [思路] 显然我们要先产生目标串中包含的极大回文字符串. Manacher求出每个位置可以向两边延伸的最长 ...

  7. BZOJ 3790 神奇项链(manacher+DP+树状数组)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3790 [题目大意] 问最少用几个回文串可以构成给出串,重叠部分可以合并 [题解] 我们 ...

  8. BZOJ_2099_[Usaco2010 Dec]Letter 恐吓信_后缀自动机+贪心

    BZOJ_2099_[Usaco2010 Dec]Letter 恐吓信_后缀自动机 Description FJ刚刚和邻居发生了一场可怕的争吵,他咽不下这口气,决定佚名发给他的邻居 一封脏话连篇的信. ...

  9. BZOJ 4327: JSOI2012 玄武密码 后缀自动机

    Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) # ...

随机推荐

  1. Head First Java学习笔记

    1.基本概念 1.1.工作方式 源代码(.java)---编译器(执行javac程序)---产生字节码(.class与平台无关)---JAVA虚拟机(JVM,读取与执行字节码) 1.2.汇编语言是对基 ...

  2. c#聊聊文件数据库kv

    现在有很多KV嵌入式存储,或者已经增加的.leveldb,RaptorDB等,都是相对比较好的存储.基本存储,一般配置.大概在6w/s左右.当然还有缓存等设置问题.这些基本是字符串和int的存储,对于 ...

  3. Jboot使用appassembler-maven-plugin插件生成启动脚本

    appassembler-maven-plugin介绍: 使用appassembler-maven-plugin插件可自动生成跨平台的启动脚本,可省去手工写脚本的麻烦,而且还可以生成jsw的后台运行程 ...

  4. Linux awk命令用法

    概述 awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理 awk工作流程是这样的:读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0 ...

  5. 转:AbstractQueuedSynchronizer的介绍和原理分析

    引自:http://ifeve.com/introduce-abstractqueuedsynchronizer/ 简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同 ...

  6. react之styled-components(基础篇)

    介绍 它是react的一个库,可以用来美化组件 它的写法依赖于es6,依赖于webpack 安装 -yarn add styled-components 基本使用的一些方法 -as -Adapting ...

  7. CSS中的动画

    1.transition 在CSS3中,可以通过transition为元素从一种样式变换为另外一种样式的过程添加效果. transition为简写属性,用于在一个属性中设置四个过渡属性,分别是: tr ...

  8. spark源码编译记录

    spark在项目中已经用了一段时间了,趁现在空闲,下个源码编译在IDEA里面阅读下,特此记录过程. 前提已经安装maven和git 1.上官网下载源码的包: 2.然后解压到一个文件夹 3.编译,编译的 ...

  9. hadoop学习笔记——zookeeper平台搭建

    zookeeper是一个自动管理分布式集群的一个工具,以实现集群的高可用. 比如集群中的一个机器挂掉了,没有zookeeper的话就得考虑挂一个机器对剩下集群工作的影响,而有了zookeeper,它就 ...

  10. 【Android】导航栏(加图片icon)和不同页面的实现(viewpager+tablayout)

    先上图,然后说大致步骤,最后再说细节 图片效果:依序点击导航栏左一.左二.中.右二.右一,最后直接滑动页面(不依靠导航栏切换) 大致步骤如下(文末会有完整代码) [1]创建一个类,我这里取名TabBa ...