Codeforces 1326D2 - Prefix-Suffix Palindrome (Hard version)

Subject to the effect

T sets of data, each given a string s

Seeking a longest string t, satisfy:

  1. t is a palindromic sequence
  2. B = A + T, A is a prefix of string s, b s suffix string , '+' is spliced two strings, ab string may be empty


data range

No more than the number of data sets 1e5

A total length of the string does not exceed 1e6


Problem-solving ideas

(Standard practice should be hashed)

Since for any string T, provided R (T) of the inverted T

The T + palindromic sequence + R (T) is still a palindromic sequence

Double pointer directly find the longest T and R (T) in the s

while(L<R&&s[L]==s[R])
    L++,R--;

(This step above O (n) can not be omitted)


However, because a large number of characters within the data range, it can not continue Easy version of O (n ^ 2) Violence

It is easy to think, for the remaining intermediate sub-strings, and in order to obtain the longest sides adjacent palindromic sequence

Can be calculated using Manacher algorithm to add (n) O Processing

Incoming two variables l and r in the initialization function, the characters can be expressed in the process as long as [l, r) section

void initStr(int l,int r){
    int k=0;
    str[k++]='@';
    for(int i=l;i<=r;i++){
        str[k++]='#';
        str[k++]=s[i];
    }
    str[k++]='#';
    len=k;
    str[k]='\0';
}


In Manacher process, a calculated value can be determined once Len is not adjacent to the left and right or

void manacher(){
    int mx=0,id=0;
    for(int i=1;i<len;i++){
        if(mx>i)
            Len[i]=min(mx-i,Len[2*id-i]);
        else
            Len[i]=1;
        while(str[i+Len[i]]==str[i-Len[i]])
            Len[i]++;
        if(Len[i]+i>mx){
            mx=Len[i]+i;
            id=i;
        }
        
        if(i==Len[i])//说明此时这个回文串左相邻
            if(TP<Len[i])
                TP=Len[i]-1,GR=1;
        if(i+Len[i]==len)//说明此时这个回文串右相邻
            if(TP<Len[i])
                TP=Len[i]-1,GR=2;
    }
}

The above code, TP indicates the longest length of palindromic sequence, GR 1 adjacent a left, a right adjacent 2


Finally, the output + in + right to left





The complete code

(77ms / 2000ms)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+50;

string s;
char str[MAXN*2];
int Len[MAXN*2],len,TP,GR;

void initStr(int l,int r){
    int k=0;
    str[k++]='@';
    for(int i=l;i<=r;i++){
        str[k++]='#';
        str[k++]=s[i];
    }
    str[k++]='#';
    len=k;
    str[k]='\0';
}

void manacher(){
    int mx=0,id=0;
    for(int i=1;i<len;i++){
        if(mx>i)
            Len[i]=min(mx-i,Len[2*id-i]);
        else
            Len[i]=1;
        while(str[i+Len[i]]==str[i-Len[i]])
            Len[i]++;
        if(Len[i]+i>mx){
            mx=Len[i]+i;
            id=i;
        }
        
        if(i==Len[i])
            if(TP<Len[i])
                TP=Len[i]-1,GR=1;
        if(i+Len[i]==len)
            if(TP<Len[i])
                TP=Len[i]-1,GR=2;
    }
}

void solve()
{
    cin>>s;
    int LEN=s.size();
    
    int L=0,R=LEN-1;
    while(L<R&&s[L]==s[R])
        L++,R--;
    
    if(L>=R)
    {
        cout<<s<<'\n';
        return;
    }
    
    initStr(L,R);
    TP=0;
    manacher();
    for(int i=0;i<L;i++)
        cout<<s[i];
    if(GR==1)
    {
        for(int i=L,j=0;j<TP;i++,j++)
            cout<<s[i];
    }
    else
    {
        for(int i=R-TP+1;i<=R;i++)
            cout<<s[i];
    }
    for(int i=R+1;i<LEN;i++)
        cout<<s[i];
    
    cout<<'\n';
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;cin>>T;
    while(T--)
        solve();
    
    return 0;
}

Guess you like

Origin www.cnblogs.com/stelayuri/p/12529117.html