BZOJ3790神奇項鏈——manacher+貪心
阿新 • • 發佈:2019-02-08
math its while 表示 ans 題目 bzoj3 最長回文串 queue
多行,每行一個答案表示最少需要使用第二個機器的次數。
abacada
abcdef
2
5
題目描述
母親節就要到了,小 H 準備送給她一個特殊的項鏈。這個項鏈可以看作一個用小寫字 母組成的字符串,每個小寫字母表示一種顏色。為了制作這個項鏈,小 H 購買了兩個機器。第一個機器可以生成所有形式的回文串,第二個機器可以把兩個回文串連接起來,而且第二個機器還有一個特殊的性質:假如一個字符串的後綴和一個字符串的前綴是完全相同的,那麽可以將這個重復部分重疊。例如:aba和aca連接起來,可以生成串abaaca或 abaca。現在給出目標項鏈的樣式,詢問你需要使用第二個機器多少次才能生成這個特殊的項鏈。輸入
輸入數據有多行,每行一個字符串,表示目標項鏈的樣式。輸出
樣例輸入
abcdcbaabacada
abcdef
樣例輸出
02
5
提示
每個測試數據,輸入不超過 5行 每行的字符串長度小於等於 50000 將每個回文串看作一個線段,那麽問題就變成至少多少個線段能將區間全部覆蓋。用manacher求一下以每個位置為中心的最長回文串,將其視為一個線段然後按左端點排序貪心選線段即可。#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<vector> #include<bitset> #include<cstring> #include<iostream> #include<algorithm> #define ll long long using namespace std; char s[100010]; int len[100010]; int n; int mx,num; struct miku { int l,r; }a[100010]; bool cmp(miku a,miku b) { return a.l<b.l; } int main() { while(scanf("%s",s+1)!=EOF) { n=strlen(s+1); 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]=‘^‘; mx=0,num=0; for(int i=1;i<=n;i++) { len[i]=mx>i?min(len[num*2-i],mx-i):1; while(s[i+len[i]]==s[i-len[i]]) { len[i]++; } if(mx<i+len[i]) { mx=i+len[i]; num=i; } } for(int i=1;i<=n;i++) { a[i].l=i-len[i]+1; a[i].r=i+len[i]-1; } 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; } } printf("%d\n",ans-1); } }
BZOJ3790神奇項鏈——manacher+貪心