zoukankan      html  css  js  c++  java
  • 【题解】P5446 [THUPC2018]绿绿和串串(manacher)

    【题解】P5446 [THUPC2018]绿绿和串串(manacher)

    考虑对于一个串进行(f)操作,就是让他变成一个以最后一个节点为回文中心的回文串。

    那么对于某个位置(p),假如它是一个合法的位置,那么它一直倍增一直倍增当长度大于这个原串的时候就使得(T)出现过一次了。

    • 倍长一次就大于原串了,此时(p)是一个回文中心,且(p)的回文半径到达了(|T|)
    • 倍长两次才大于原串,此时(S)倍增一次后的那个点(p')是一个回文中心,且(p')的回文边界到达了右边界。但为了保证第一次倍增的合法性,此时原(p)这个位置的回文半径要顶着(1)节点。
    • 倍长三次...

    递归地思考,一个位置合法当且仅当这个位置的回文边界顶到原串右边界,或者他的右边界的那个位置合法且自己的左边界顶到原串左边界。

    用manacher实现即可,注意一个细节,就是马拉车对于每个非辅助字符的字符,他为中心的回文串的回文边界上的字符一定是个辅助字符,要减去(1)以达到效果。

    复杂度(O(2sum |S|))

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;  typedef long long ll; 
    inline int qr(){
          register int ret=0,f=0;
          register char c=getchar();
          while(c<48||c>57)f|=c==45,c=getchar();
          while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
          return f?-ret:ret;
    }
    
    const int maxn=1e6+5;
    char s[maxn<<1];
    bool f[maxn<<1];
    int p[maxn<<1],cnt,n;
    inline void manacher(){
          s[0]='~',s[cnt=1]='|';
          char c=getchar();
          while(c<'a'||c>'z') c=getchar();
          while(c>='a'&&c<='z') s[++cnt]=c,s[++cnt]='|',c=getchar();
          s[cnt+1]='';
          for(int t=1,r=0,mid=0;t<=cnt;++t){
    	    p[t]=0;
    	    if(r>=t) p[t]=min(r-t+1,p[(mid<<1)-t]);
    	    while(s[t-p[t]]==s[t+p[t]]) ++p[t];
    	    if(t+p[t]-1>r) r=t+p[t]-1,mid=t;
          }
    }
    
    int main(){
          n=qr();
          for(int t=1;t<=n;++t){
    	    manacher();
    	    for(int t=cnt;t;--t) f[t]=0,f[t]=(t+p[t]-1==cnt)||(t-p[t]+1==1&&f[t+p[t]-2]);
    	    for(int t=2;t<=cnt;t+=2) if(f[t]) printf("%d ",t>>1);
    	    putchar('
    ');
          }
          return 0;
    }
    
    
    
  • 相关阅读:
    关于表单的jQuery练习
    jQuery中的综合动画
    jQuery中自定义简单动画的实现
    清除浮动
    定位
    盒子模型
    笔记
    笔记
    翻页
    DOM
  • 原文地址:https://www.cnblogs.com/winlere/p/11598697.html
Copyright © 2011-2022 走看看