bzoj3790 神奇项链

http://www.elijahqi.win/2018/02/22/bzoj3790/
Description

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

Input

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

Output

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

Sample Input

abcdcba
abacada
abcdef
Sample Output

0
2
5
HINT

每个测试数据,输入不超过 5行
每行的字符串长度小于等于 50000
忘记判断偶回文串了wa很久
题意:用最少的回文串覆盖整个序列 首先manacher求出所有回文串 然后按照左端点排序 依次枚举 贪心选择最长 统计覆盖次数 输出答案-1 即可 另外这个转换线段的时候得思考下manacher的工作原理有+1-1的小细节

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 110000
using namespace std;
struct node{
    int l,r;
}line[N];
inline bool cmp(const node &a,const node &b){
    return a.l<b.l;
}
char s[N],s1[N];int p[N];
int main(){
    freopen("bzoj3790.in","r",stdin);
    while(~scanf("%s",s1+1)){
        int n=strlen(s1+1);n<<=1;++n;
        for (int i=1;i<=n;++i) s[i]=(i&1)?'#':s1[i>>1];
        int mx=0,id=0;
        for (int i=1;i<=n;++i){
            if (i<mx) p[i]=min(p[(id<<1)-i],mx-i);else p[i]=1;
            while(i-p[i]>0&&i+p[i]<=n&&s[i-p[i]]==s[i+p[i]]) ++p[i];
            if (i+p[i]>mx) mx=i+p[i],id=i;
            line[i].l=i-p[i]+2>>1,line[i].r=i+p[i]-2>>1;
        }int nn=n;
        n>>=1;sort(line+1,line+nn+1,cmp);int ans=0,pl=0,now=1;
        while(pl<n){
            mx=0;while(line[now].l<=pl+1) mx=max(mx,line[now].r),++now;
            ++ans;pl=mx;
        }printf("%d\n",ans-1);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值