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

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

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

Sample Input
abcdcba
abacada
abcdef

Sample Output
0
2
5

HINT
每个测试数据,输入不超过 5行
每行的字符串长度小于等于 50000

Source

思路
manacher加上线段区间覆盖问题。
找出以每个点为中心的最大的回文串,然后做一遍区间覆盖,显然答案就是最少需要覆盖的数量减去1。

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>

const int maxn=50000;

struct data
{
  int x,y;

  bool operator <(const data &other) const
  {
    return x<other.x;
  }
};

data d[maxn+10];
char s[maxn+10],a[(maxn<<1)+10];
int p[(maxn<<1)+10],id,rmax,len;

int solve()
{
  len=strlen(s+1);
  a[0]='!';
  a[1]='$';
  for(register int i=1; i<=len; ++i)
    {
      a[i<<1]=s[i];
      a[i<<1|1]='$';
    }
  len=len<<1|1;
  a[len+1]='*';
  memset(p,0,sizeof p);
  id=1;
  p[1]=1;
  rmax=1;
  for(register int i=2; i<=len; ++i)
    {
      if(i>rmax)
        {
          p[i]=1;
        }
      else
        {
          if(p[(id<<1)-i]<rmax-i)
            {
              p[i]=p[(id<<1)-i];
            }
          else
            {
              p[i]=rmax-i;
            }
        }
      while(a[i+p[i]]==a[i-p[i]])
        {
          ++p[i];
        }
      if(i+p[i]-1>rmax)
        {
          rmax=i+p[i]-1;
          id=i;
        }
    }
  for(register int i=1; i<=len; ++i)
    {
      d[i].x=i-p[i]+1;
      d[i].y=i+p[i]-1;
    }
  std::sort(d+1,d+len+1);
  int now=1,pre=0,ans=0;
  while(now<=len)
    {
      int maxy=0;
      while((now<=len)&&(d[now].x-1<=pre))
        {
          if(d[now].y>maxy)
            {
              maxy=d[now].y;
            }
          ++now;
        }
      if(now<=len)
        {
          ++ans;
        }
      pre=maxy;
    }
  printf("%d\n",ans-1);
  return 0;
}

int main()
{
  while(scanf("%s",s+1)!=EOF)
    {
      solve();
    }
  return 0;
}