P3279-[SCOI2013]密码【Manacher】
生活随笔
收集整理的這篇文章主要介紹了
P3279-[SCOI2013]密码【Manacher】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.org/problemnew/show/P3279
題目大意
一個字符串滿足:
求滿足要求的字典序最小的字符串。
解題思路
因為字典序最小,所以優先滿足前面的最小。我們可以找出相同不相同的關系。然后對于每段相等關系就將前面的一半復制到后面去
這樣是O(n2)O(n^2)O(n2)的,并不能勝任此題,我們可以發現很多關系都是重復的,所以需要使用ManacherManacherManacher逆推找出O(n)O(n)O(n)的關系。
我們先將字符串的間隙之間插入′?′'*'′?′字符然后現在我們這知道每個串為中心的回文串,用fi,jf_{i,j}fi,j?表示第iii個位置不可以填jjj這個字符,rir_iri?表示以iii為中心的最長回文串長度。
一個位置會被更新多次,我們考慮兩種情況
然后要注意中間的不相等情況也需要O(1)O(1)O(1)更新
然后更新maxrightmaxrightmaxright
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=2e5+100; int n,r[N],maxn,pos; bool f[N][26]; char str[N]; int main() {scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&r[i*2-1]),r[i*2-1]++;for(int i=1;i<n;i++)scanf("%d",&r[i*2]),r[i*2]++;n=n*2;str[0]='*';str[1]='a';r[0]=1;for(int i=0,mr=-1;i<=n;i++){int j=0;if(!(i&1)) str[i]='*';else if(str[i]<'a'){for(;j<26;j++)if(!f[i][j]) break;str[i]=j+'a';}if(maxn>i) j=min(maxn-i+1,r[2*pos-i]);else j=1;for(j--;j<r[i];j++) str[i+j]=str[i-j];if(r[i]<=i) f[i+r[i]][str[i-r[i]]-'a']=1;if(maxn<i-j+1) maxn=i+r[i]-1,pos=i;}for(int i=1;i<=n;i+=2)printf("%c",str[i]); }總結
以上是生活随笔為你收集整理的P3279-[SCOI2013]密码【Manacher】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 炉石对电脑配置要求(炉石对电脑配置)
- 下一篇: P3934-Nephren Ruq In