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. 【Django笔记二】Django2.0配置模板和静态文件

    一.环境版本信息: 操作系统:windows10 Django版本:2.0.5 Python版本:3.6.4 二.创建模板 1.在my_project文件夹下新建文件夹templates用于存放模板文 ...

  2. 竞赛题解 - Karp-de-Chant Number(BZOJ-4922)

    Karp-de-Chant Number(BZOJ-4922) - 竞赛题解 进行了一次DP的练习,选几道题写一下博客~ 标签:BZOJ / 01背包 / 贪心 『题目』 >> There ...

  3. chromium之ScopedNSAutoreleasePool浅析

    上代码,看看注释 ScopedNSAutoreleasePool只有Mac系统特有的,也可以理解为OC特有的函数, 其他系统为空实现   // On the Mac, ScopedNSAutorele ...

  4. Linux 学习第三天

    一.常用命令 1.diff A.diff -q 源文件 目标文件  (快速比较文件是否相同) 2.ifconfig.nmcli (查看配置信息) 命令输入注意: Windows 查看网卡配置信息输入命 ...

  5. 针对jquery的ajax中的参数理解

    1. url 发送请求的地址.为空表示当前页. $.ajax({ type: "post", data: studentInfo, contentType: "appli ...

  6. jQuery实现简单的拼图游戏

    一,实现拼图的搭建: <div class="box"> <table id="table1" class="mytable&quo ...

  7. SSM+poi导入和导出

    最原始数据 导入成功后 下载数据 下载后的数据显示 数据变成16条 点击导出可选择 导了两次  看数据变化 数据库字段在下面地址给出 首先贴出Dao层 List<User> findAll ...

  8. Css Sprite(雪碧图、精灵图)<图像拼合技术>

    一.精灵图使用场景: 二.Css Sprite(优点) 减少图片的字节. 减少网页的http请求,从而大大的提高页面的性能. 解决了网页设计师在图片命名上的困扰,只需对一张集合的图片上命名就可以了,不 ...

  9. Python支付接口汇总大全(包含微信、支付宝等)

    微信接口 wzhifuSDK- 由微信支付SDK 官方PHP Demo移植而来,v3.37下载地址 weixin_pay- 是一个简单的微信支付的接口 weixin_pay- 微信支付接口(V3.3. ...

  10. MCUXpresso release build 时提示GFLIB等函数未引用的问题

    MCUXpresso release build 时提示 GFLIB 等函数未引用的问题 最近在使用 MCUXpresso 编译工程时选择 Debug(Debug build) 能顺利编译,但是选择 ...