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. Spring知识点小结汇总

    Spring部分 1.谈谈你对spring IOC和DI的理解,它们有什么区别? IoC Inverse of Control 反转控制的概念,就是将原本在程序中手动创建UserService对象的控 ...

  2. python函数基本介绍

    函数 1.函数结构 def 是函数的定义关键字,my_len是函数名.()传参用,冒号下面都是函数体. 执行函数方法:函数名加括号来执行函数.My_len() 举例: # s = 'lkfjsjulk ...

  3. vue-cli 3.0 使用axios配置跨域访问豆瓣接口

    vue-cli 3.0 配置axios跨域访问豆瓣接口 自己做的小demo 由于豆瓣api跨域问题,因此不能直接通过ajax请求访问,我们通过vue-cli提供给我们的代理 进行配置即可, 在根目录下 ...

  4. es6 Reflect对象详解

    Reflect是ES6为操作对象而提供的新API,而这个API设计的目的只要有: 将Object对象的一些属于语言内部的方法放到Reflect对象上,从Reflect上能拿到语言内部的方法.如:Obj ...

  5. linux 下安装 Cisco Packet Tracer 7.11以及一些注意

    https://blog.csdn.net/qq_35882901/article/details/77652571 https://linux.cn/article-5576-1.html 开启登录 ...

  6. SQL Server服务器角色和数据库角色描述

    服务器角色 bulkadmin 这个角色可以运行BULK INSERT语句.该语句允许从文本文件中将数据导入到SQL Server2008数据库中,为需要执行大容量插入到数据库的域帐号而设计. dbc ...

  7. RMI入门HelloWorld

    java RMI(Remote Method Invocation)是一种基于java远程调用技术,是对RPC的java实现,可以在不同主机上进行通信与方法调用.PRC通信原理如图: 方法调用从客户对 ...

  8. Hibernate学习笔记一

    1 框架体系结构 2 hibernate入门 2.1 ORM框架 Hibernate是一个数据持久化层的ORM框架. Object:对象,java对象,此处特指JavaBean Relational: ...

  9. axios请求封装和异常统一处理

    前端网络请求封装前端采用了axios来处理网络请求,为了避免在每次请求时都去判断各种各样的网络情况,比如连接超时.服务器内部错误.权限不足等等不一而足,我对axios进行了简单的封装,这里主要使用了a ...

  10. 20145202马超《网络对抗》Exp8 Web基础

    1.本实践的具体要求有: (1).Web前端HTML(1分) 能正常安装.启停Apache.理解HTML,理解表单,理解GET与POST方法,编写一个含有表单的HTML. (2).Web前端javas ...