神奇项链

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;
}

原文地址:https://www.cnblogs.com/Wolfycz/p/8414486.html

时间: 2024-10-22 06:49:05

神奇项链的相关文章

【BZOJ-3790】神奇项链 Manacher + 树状数组(奇葩) + DP

3790: 神奇项链 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 304  Solved: 150[Submit][Status][Discuss] Description 母亲节就要到了,小 H 准备送给她一个特殊的项链.这个项链可以看作一个用小写字母组成的字符串,每个小写字母表示一种颜色.为了制作这个项链,小 H 购买了两个机器.第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个

【BZOJ】【3790】神奇项链

Manacher算法/DP 找出所有的回文串,看做是一个个线段,那么问题就转化成了用最少的线段将整个区间覆盖起来,可以重叠,那么这就是一个DP了= = Orz ZKY大爷,让蒟蒻开眼界了……头一次知道原来树状数组还可以反过来用0.0 1 /************************************************************** 2 Problem: 3790 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6

bzoj3790 神奇项链

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

BZOJ 3790 神奇项链 hash/后缀自动机+贪心

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

【bzoj3790】神奇项链——manacher+贪心

听说这道题可以用树状数组什么鬼的做,反正我不会,还是老老实实打manacher+贪心大法吧-- 我们只要在跑manacher的过程中,用一个结构体(也可以直接用数组)来记录以每个字符为对称轴的最长回文的最左端和最右端,然后就得到了一些线段,于是问题完美地转换成了求取最少段的线段来完全覆盖一个区间了,直接排完序后贪心一遍即可.当然这里面有些比较是不必要的,但我也懒得去优化了. 具体实现细节看代码: #include<cstdio> #include<cstring> #include

【BZOJ3790】神奇项链(manacher,树状数组)

题意: 思路:生成一些回文拼起来使生成的段数最小 显然存在一种最优的方案,使生成的那些回文是目标串的极长回文子串 求出对于每个位置的最长回文子串,问题就转化成了: 给定一些已知起始和终止位置的线段,求覆盖住整个区域的最小线段数量 这个可以BIT做,求当前已经覆盖的区域最远能拓展到哪里 也可以预处理一下前缀最小值,跳转时直接调用即可 1 const oo=1000000000; 2 var t,a,x,y,p:array[1..110000]of longint; 3 len,n,i,id,mx,

BZOJ 3790 神奇项链 Hash+二分

题目大意:给出一个字符串,求出这是最少由多少个回文串组成的.回文串可以重叠. 思路:将原串中的所有回文串都统计出来,然后变成一些区间,问题就转化成了区间并的问题. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 400010 #define BASE 1333 #define INF 0x3f3f3f3f using

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

[题意] 你可以产生一个回文串,也可以将两个串合并成一个串,问产生目标串需要的最少合并次数. [思路] Manacher求出每个位置可以向两边延伸的最长回文串. 则题目转化为有若干条线段,求最少的线段将[1..n]覆盖.贪心DP皆可上,DP需要BIT优化一下. [代码] 1 #include<set> 2 #include<cmath> 3 #include<queue> 4 #include<vector> 5 #include<cstdio>

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

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3790 [题目大意] 问最少用几个回文串可以构成给出串,重叠部分可以合并 [题解] 我们先用manacher处理出每个位置最长的回文串, 那么题目就转化为求最少的线段来覆盖全区间,那就是经典的dp题了, dp[i]=min(dp[j]+1)(i线段的左端点-1和j线段的右端点有交) 用树状数组优化一下即可. [代码] #include <cstdio> #include <al