人生如此复杂,机会多得像稠密图,我们没理由认输。尽管我们走不了最短路,但图仍是连通图。TLE之前,没有一个节点叫失败。(You know what's cooking? BOOM~~)!

manacher---神奇项链

神奇项链

时间限制 : - MS   空间限制 : - KB 
评测说明 : 1s,64m
问题描述

母亲节就要到了,小 H 准备送给她一个特殊的项链。
这个项链可以看作一个用小写字母组成的字符串,每个小写字母表示一种颜色。

为了制作这个项链,小 H 购买了两个机器。
第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:
   假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。例如:aba和aca连接起来,可以生成串abaaca或 abaca。

现在给出目标项链的样式,询问你需要使用第二个机器多少次才能生成这个特殊的项链。

输入格式

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

输出格式

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

样例输入 1

abcdcba
abacada
abcdef 

样例输出 1

0
2
5

样例输入 2

xuqeytcixfzpzvcacymqncdohedfyowmipplplkyrsaspjliczflordhlbckyiuqxkslntofajs
amjmaekzbnbwagotspirvjksendltyeeuswefpdcdmmhzomlvkrhtwidlybkvvvebqkmvednaxddeygghrvqfaxwjssvcphcrzeauwlowwdmhacpzbnihgmbypfsblvsyaugkcg

样例输出 2

65
118

提示

每个测试数据,输入不超过 5行

每行的字符串长度小于等于 50000 

 

1.通过马拉车找出所有回文子串,把每个回文子串看作一条线段
2.问题变成选最少的线段将整个区间覆盖,即最小区间覆盖问题。贪心即可。

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
char s[100010];
int len[100010];//回文串长度
int n;
struct Node
{
    int l,r;
} a[100010];
bool cmp(Node a,Node b)//按左端点贪心排序
{
    return a.l<b.l;
}
void Init()
{
    for(int i=n; i>=1; i--)
    {
        s[i<<1]=s[i];
        s[i<<1|1]='&';
    }
    n=n<<1|1;
    s[0]='%';
    s[1]='&';
    s[n+1]='^';
}
void manacher()
{
    int maxright=0,num=0;
    for(int i=1; i<=n; i++)
    {
        if(i<maxright)
            len[i]=min(len[num*2-i],maxright-i);
        else
            len[i]=1;
        while(s[i+len[i]]==s[i-len[i]])
        {
            len[i]++;
        }
        if(maxright<i+len[i])
        {
            maxright=i+len[i];
            num=i;
        }
    }
}
int main()
{
    while(scanf("%s",s+1)!= EOF)//从第一位开始算 
    {
        n=strlen(s+1);
        Init();
        manacher();
        for(int i=1; i<=n; i++)
        {
            a[i].l=i-len[i]+1;//以i为中心的左长度 
            a[i].r=i+len[i]-1;//以i为中心的右长度
        }
        sort(a+1,a+1+n,cmp);
        int r=0,ans=0,i=1;
        while(i<=n)
        {
            int sum=0;
            while(a[i].l-1<=r&&i<=n)
            {
                sum=max(sum,a[i].r);
                i++;
            }
            ans++;//现长
            r=sum;//覆盖完全
            if(r==n)
            {
                break;
            }
            //ans++;
        }
        cout<<ans-1<<endl;
    }
}

 

posted @ 2019-08-14 10:07  CXYscxy  阅读(272)  评论(0编辑  收藏  举报
Live2D