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