zoukankan      html  css  js  c++  java
  • 马拉车+贪心——cf1326D

    好好的马拉车不用,非要用回文树,结果调了半天

    枚举回文中心位置,看这个位置的回文串是否可以和前缀或后缀接上,如果能接上,算答案的时候要优先取前后缀,即可能会截掉一部分回文串的两侧

    用马拉车在s_new上非常方便处理

    #include<bits/stdc++.h>
    using namespace std;
    #define N 2000005
    
    char s[N],s_new[N];
    int init(){
        int len=strlen(s);
        int j=2;
        s_new[0]='$',s_new[1]='#';
        for(int i=0;i<len;i++)
            s_new[j++]=s[i],s_new[j++]='#';
        s_new[j]=0;
        return j;
    }
    int start,p[N],n;
    int manacher(){
        int len=init();
        int mx=0,id;
        start=0;
        for(int i=0;i<len;i++){
            if(mx>i)p[i]=min(p[id*2-i],mx-i);
            else p[i]=1;
            while(s_new[i-p[i]]==s_new[i+p[i]])p[i]++;
            if(mx<i+p[i])
                mx=i+p[i],id=i;
        }
    }
    int lens[N],POS;
    
    int main(){
        int t;cin>>t;
        while(t--){
            cin>>s;
            n=strlen(s);
            manacher();
            for(int i=1;i<=n*2+1;i++)
                lens[i]=p[i];
            n=n*2+1;
            
            POS=0;
            for(int i=1;i<=(n+1)/2;i++)
                if(s_new[i]==s_new[n-i+1])POS=i;
                else break;
            int Max=POS*2,pos1=POS,pos2=n-POS+1,flag=0;
            for(int i=POS+1;i<=n-POS;i++){
                int pre=i-lens[i];
                int suf=i+lens[i];
                if(pre>POS && suf<n-POS+1)continue;
                if(POS-pre>=suf-(n-POS+1)){
                    pre=POS+1;
                    suf=2*i-pre;
                    if(Max<2*POS+suf-pre+1){
                        Max=2*POS+suf-pre+1;
                        pos1=suf;pos2=n-POS+1;
                    }
                }else{
                    suf=n-POS;
                    pre=2*i-suf;
                    if(Max<2*POS+suf-pre+1){
                        Max=2*POS+suf-pre+1;
                        pos1=POS;pos2=pre;
                    }
                }
            }
            if(pos1>=pos2)flag=1;
            
            if(flag){
                cout<<s<<'
    ';
            }else {
                for(int i=1;i<=pos1;i++)
                    if(s_new[i]!='#')cout<<s_new[i];
                for(int i=pos2;i<=n;i++)
                    if(s_new[i]!='#')cout<<s_new[i];
                puts("");
            }
        }
    }
    /*
    #a#c#b#b#a#
    */ 
  • 相关阅读:
    Java 学习笔记之 线程interrupted方法
    Java 学习笔记之 线程interrupt方法
    定义函数
    调用函数
    pass语句
    循环
    条件语句
    别样赋值
    import语句
    字典方法
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12530986.html
Copyright © 2011-2022 走看看