[BZOJ-3676] && [CodeForces-245H]: base application tree palindromic

Questions surface: BZOJ --- 3676

Meaning of the questions:

The nature of the string is determined for all the different number and length of palindromic sequence

analysis:

Nothing good analysis, is a palindrome bare tree problem, I recommend reading: Palindrome tree [a class of powerful tools palindrome string handling issues]

Talk about some of my understanding:

Each node of the tree represents a palindromic nature different palindrome sequence, and the like AC automaton, but also fail a pointer to the current does not include its own node palindrome longest suffix where each character is added, by jump fail pointer longest palindrome string to find and the characters matched; and finally how many nodes there are that many different nature palindrome string (of course minus two root nodes), and then to fail from the leaf node of the tree the jump, the statistics of the different nature of each palindromic number (because the longer palindromic sequence must contain a short palindrome string suffix), the following code location ①② can not be exchanged, otherwise fail pointer may point to themselves , resulting in an infinite loop

Code:

#include <bits/stdc++.h>
 
using namespace std;
const int maxn = 3e5+55;
struct PalindromicTree{
    int p,n,last,fail[maxn],tr[maxn][26],s[maxn],len[maxn],cnt[maxn];
    int newnode(int Len){
        for(int i = 0;i < 26; ++i) tr[p][i] = 0;
        len[p] = Len; cnt[p] = 0;
        return p++; 
    }
    void init(){
         p = n = last = 0;
         newnode(0);newnode(-1);
         fail[0] = 1;s[0] = -1;
    }
    int getfail(int x){
        while(s[n-len[x]-1] != s[n]) x = fail[x];
        return x;
    }
    void add(int x){
        s[++n] = x;
        int cur = getfail(last);
        if(!tr[cur][x]){
            int now = newnode(len[cur]+2);
            fail[now] = tr[getfail(fail[cur])][x]; //①
            tr[cur][x] = now;                      //②              
        } 
        last = tr[cur][x];
        cnt[last]++;
    }
    void count(){
        for(int i = p-1;i > 0; --i) cnt[fail[i]] += cnt[i];
    }
}T;
char ss[maxn];
int main(){
    scanf("%s",ss);
    int len = strlen(ss);
    T.init();
    for(int i = 0;i < len; ++i) T.add(ss[i]-'a');
    T.count();
    long long ans = 0LL; 
    for(int i = 0;i < T.p; ++i) ans = max(ans,1LL*T.len[i]*T.cnt[i]);
    printf("%lld",ans);
    return 0;
}

 

Questions surface: codeforces --- 245H

Meaning of the questions:

Gives a maximum string length 5000 times and 1e6 query, the number of sections to a palindromic sequence

analysis:

Application of palindromic automaton array num, num [now] = num [ fail [now]] + 1, x can be determined with the first character of a palindromic sequence at the end of the palindromic sequence number, because the nodes are now s [x] at the end of the palindromic sequence, Fail [now] are to s [x] at the end of the palindromic sequence, as Fail [now] are now suffix; and strings are of different nature such palindromic

Then we can get statistics palindrome string prefix and the current prefix number, the starting point of this topic from each ran again, the answer can be pretreated

Code:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const int mod = 1e9+7;
const int maxn = 5e3+53;
struct PalindromicTree{
    int last,tot,n,s[maxn],len[maxn],fail[maxn],num[maxn],tr[maxn][27];
    int newnode(int Len){
        for(int i = 0;i < 27; ++i) tr[tot][i] = 0;
        len[tot] = Len;
        num[tot] = 0;
        return tot++;
    }
    void init(){
        last = tot = n = 0;
        newnode(0),newnode(-1);
        fail[0] = 1; s[0] = -1;
    }
    int getfail(int x){
        while(s[n-len[x]-1] != s[n]) x = fail[x];
        return x;
    }
    int add(int x){
        s[++n] = x;
        int cur = getfail(last);
        if(!tr[cur][x]){
            int now = newnode(len[cur]+2);
            fail[now] = tr[getfail(fail[cur])][x];
            tr[cur][x] = now;
            num[now] = num[fail[now]]+1; 
        } 
        last = tr[cur][x];
        return num[last];        //返回以当前节点结尾的回文串的数量
    }
}T;
char ss[maxn];
int q,l,r,sum[maxn][maxn];
int main(){
    scanf("%s %d",ss+1,&q);
    int len = strlen(ss+1);
    for(int i = 1;i <= len; ++i){
        T.init();
        for(int j = i; j <= len; ++j){
            sum[i][j] = sum[i][j-1] + T.add(ss[j]-'a');
        }
    }
    while(q--){
        scanf("%d %d",&l,&r);
        printf("%d\n",sum[l][r]);
    }
    return 0;
}

 

Questions surface: the longest common substring palindrome

Meaning of the questions:

The longest common to find two sub-strings strings palindromic

analysis:

First built in the first string a palindrome tree, label each node from the first string, and from The tree roots even starting to run again the second string, if it reaches the first node string, take the maximum length can, this method can be obtained for several palindromic sequence longest common substring

Code:

#include <bits/stdc++.h>
 
using namespace std;
const int maxn = 3e5+55;
struct PalindromicTree{
    int p,n,ans,last,fail[maxn],tr[maxn][26],s[maxn],len[maxn],cnt[maxn];
    int newnode(int Len){
        for(int i = 0;i < 26; ++i) tr[p][i] = 0;
        len[p] = Len; cnt[p] = 0;
        return p++; 
    }
    void init(){
         p = n = last = ans = 0;
         newnode(0);newnode(-1);
         fail[0] = 1;s[0] = -1;
    }
    int getfail(int x){
        while(s[n-len[x]-1] != s[n]) x = fail[x];
        return x;
    }
    void add(int x,int op){
        s[++n] = x;
        int cur = getfail(last);
        if(!tr[cur][x]){
            int now = newnode(len[cur]+2);
            fail[now] = tr[getfail(fail[cur])][x];
            tr[cur][x] = now;
        } 
        last = tr[cur][x];
        cnt[last] |= op;
        if(cnt[last] == 3) ans = max(ans,len[last]);
    }
    void count(){
        for(int i = p-1;i > 0; --i) cnt[fail[i]] += cnt[i];
    }
}T;
char ss[maxn];
int main(){
    while(~scanf("%s",ss)){
        T.init();
        int len = strlen(ss);
        for(int i = 0;i < len; ++i) T.add(ss[i]-'a',1);
        scanf("%s",ss);
        len = strlen(ss);
        T.n = 0,T.last = 0;         
        for(int i = 0;i < len; ++i) T.add(ss[i]-'a',2);
        cout << T.ans << '\n';
    }
    return 0;
}

 

Guess you like

Origin blog.csdn.net/qq_41157137/article/details/92847194