神奇项链

Description

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

Input

输入数据有多行,每行一个字符串,表示目标项链的样式。
每个测试数据,输入不超过 5行
每行的字符串长度小于等于 50000

Output

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

Sample Input
abcdcba
abacada
abcdef

Sample Output
0
2
5

先Manacher,然后变成了最小线段覆盖的问题,因为不存在无解的情况,并且长度最大只有50000,因此可以有各种方法

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
    int x=0,f=1;char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}
inline void print(int x){
    if (x>=10)     print(x/10);
    putchar(x%10+'0');
}
const int N=1e5;
char s[N+10];
int p[N+10];
struct AC{
    int l,r;
    void join(int a,int b){l=a,r=b;}
    bool operator <(const AC x)const{return l<x.l;}
}A[N+10];
int main(){
    while (~scanf("%s",s+1)){
        int len=strlen(s+1);
        for (int i=len;i;i--)   s[i<<1]=s[i],s[i<<1|1]='&';
        len=len<<1|1;
        s[0]='%',s[1]='&',s[len+1]='^';
        int Max=0,ID=0;
        for (int i=1;i<=len;i++){
            p[i]=Max>i?min(p[ID*2-i],Max-i):1;
            while (s[i+p[i]]==s[i-p[i]])    p[i]++;
            if (Max<p[i]+i) Max=p[ID=i]+i;
        }
        for (int i=1;i<=len;i++)    A[i].join(i-p[i]+1,i+p[i]-1);
        sort(A+1,A+1+len);
        int r=0,ans=0,i=0;
        while (i<=len){
            int tmp=0;
            while (A[i].l-1<=r&&i<=len) tmp=max(tmp,A[i++].r);
            if (i>len)  break;
            ans++,r=tmp;
        }
        printf("%d\n",ans-1);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值