Palindrome automata PAM

Palindrome automata PAM

https://oi-wiki.org/string/pam/#_4

Temporary mouthpiece

Because it is too late to do it, first set up a set of questions and feel the question type.

Palindrome Automata (2018ACM-ICPC Nanjing Network Competition: I. Skr)

A number string of length n, which only contains numbers 1-9, find the sum of the integers represented by all palindrome strings that are essentially different

For example: "1232111": ans = 1+11+111+2+3+232+12321 = 12681

You can pre-prefix the prefix sum, and then record the position of each palindrome.


2019 Hang Dian Multi-school Two I Love Palindrome String (Palindrome Automata)

Given a string of length N, it is required to output a statistical array A of length N

A[i] represents the number of good substrings of length i

The definition of good substring is that the substring is a palindrome, and half of the substring is also a palindrome.

Preprocess the word string hash, traverse all palindrome sub-strings.


2014 Asia Xian Regional Contest G

Give two strings A and B. Find the sum of the number of occurrences of all palindromes of A in B.

It may be searching for the common part of the two trees...


2019 Niuke Summer Multi-school Training Camp (Sixth Session) C: Palindrome Mouse (Palindrome Tree + Tree Section)

https://blog.csdn.net/cymbals/article/details/98398375

Given a string Str, find the palindrome string set as S, and ask (a, b) in S to satisfy the logarithm of a substring of b.

https://ac.nowcoder.com/acm/contest/886/C

I feel that it may be related to the depth of the chain.


luogu longest double palindrome

Input the string SSS of length nnn, and find the longest double palindrome substring TTT of SSS, then TTT can be divided into two parts XXX,YYY, (∣X∣,∣Y∣≥1|X|,|Y|≥1 ∣X∣,∣Y∣≥1) and XXX and YYY are both palindrome strings.

I think it is to exclude the nodes that directly fail to connect to the root.


Cheerleader rehearsal

The general idea is to let you find all odd palindrome strings in a string, and multiply their lengths by the length of the first k.

Since the answer may be large, output the remainder after dividing by 19930726.

Horse-drawn carts can also be used, but the odd and even roots of the palindrome tree are independent and can be operated.

(But I have a horse-drawn cart with odd and even separation, which is actually okay.


"SHOI2011" double palindrome

Let t be the string after s is reversed, and find the length of the longest substring of a string like stst.

= = It turns out that this is the original question of the 19th Hangzhou Electric Power School. excuse me.


HDU 5421 Victor and String

BestCoder Round #52 (div.1)

Gives you n operations,

If it is 1, insert a character after the string,

If it is 2, insert a character in front of the string,

If it is 3, output the number of palindrome strings that are essentially different in the current string,

If it is 4, the number of palindromes of the output string is output.

It seems that pam needs to be maintained in both directions. This transformation requires basic principles and is a bit difficult.

CodeChef Palindromeness


The most recent gym also has a question. H. happy game

Thinking

struct or namespace is a problem.

Both have their own advantages.

The advantage of namespace is that if your logic is changed in a template, it will be very convenient, but you need to type scope resolution operators outside ::. And in some cases, the problem of initialization will be avoided.

The advantage of struct is that it is more convenient to use a dot symbol when combining external logic. And it is easy to make people aware of the scope of the problem.

I think both methods have merits.

In the live match, you may even have to type it directly into the overall situation (if it is a naked question)

2019 ICPC Xuzhou Station Network Competition G

https://nanti.jisuanke.com/t/41389

Title

Suppose the contribution of a palindrome string is the number of different characters it contains, then an original string is given, and the contribution of all palindrome substrings is summed.

Ideas

Knowing that PAM can traverse all palindrome substrings, you only need to know the position of each palindrome substring.

This information is well maintained.

As for the weighting, it can be done with the help of prefixes.

Code

namespace version

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int PAMN = 3e5 + 59;
namespace PAM {
    
    
    int tot, las;
    int ch[PAMN][26];
    int cnt[PAMN];
    int len[PAMN];
    int fail[PAMN];
    int npos[PAMN];

    int pos;
    char s[PAMN];

    int node(int l) {
    
    
        tot++;
        memset(ch[tot], 0, sizeof(ch[tot]));
        len[tot] = l;
        cnt[tot] = 0;
        fail[tot] = 0;
        npos[tot] = pos;	// 标记回文串第次出现的位置
        return tot;
    }

    void init() {
    
    
        tot = -1;
        las = 0;
        pos = 0;
        s[pos] = '$';   // s = '$......'
        node(0);      // node[0] : len =  0 偶根
        node(-1);     // node[1] : len = -1 奇根
        fail[0] = 1;
    }

    int jump(int u) {
    
    
        while (s[pos - len[u] - 1] != s[pos]) {
    
    
            u = fail[u];
        }
        return u;
    }

    void extend(char c) {
    
    
        s[++pos] = c;
        int d = c - 'a';
        int u = jump(las);
        if (!ch[u][d]) {
    
    
            int v = node(len[u] + 2);
            fail[v] = ch[jump(fail[u])][d];
            ch[u][d] = v;
        }
        npos[ch[u][d]] = pos; // 尝试表示每个回文串最后的位置。(删掉也对)
        las = ch[u][d];
        cnt[las]++;
    }

    int arr[PAMN][26];

    ll solve() {
    
    
        ll ans = 0;

        for (int i = tot; i > 1; i--) {
    
    
            cnt[fail[i]] += cnt[i];
        }

        for (int i = 1; i <= pos; ++i) {
    
    
            memcpy(arr[i], arr[i - 1], sizeof arr[0]);
            arr[i][s[i] - 'a']++;
        }

        for (int i = 2, l, r; i <= tot; i++) {
    
    
            ll tmp = 0;
            r = npos[i];
            l = r - len[i];
            for (int j = 0; j < 26; ++j) {
    
    
                tmp += ll(arr[l][j] < arr[r][j]);
            }
            ans += tmp * cnt[i];
        }
        return ans;
    }
};  // namespace pam

char s[PAMN];

int main() {
    
    
    PAM::init();
    scanf("%s", s + 1);
    int n = strlen(s + 1);
    for (int i = 1; i <= n; i++) {
    
    
        PAM::extend(s[i]);
    }
    printf("%lld\n", PAM::solve());
    return 0;
}

struct version

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int PAMN = 3e5 + 59;

struct PAM {
    
    
    int tot, las;
    int ch[PAMN][26];
    int cnt[PAMN];
    int len[PAMN];
    int fail[PAMN];
    int npos[PAMN];

    int pos;
    char s[PAMN];

    int node(int l) {
    
    
        tot++;
        memset(ch[tot], 0, sizeof(ch[tot]));
        len[tot] = l;
        cnt[tot] = 0;
        fail[tot] = 0;
        npos[tot] = pos;
        return tot;
    }

    void init() {
    
    
        tot = -1;
        las = 0;
        pos = 0;
        s[pos] = '$';   // s = '$......'
        node(0);      // node[0] : len =  0 偶根
        node(-1);     // node[1] : len = -1 奇根
        fail[0] = 1;
    }

    int jump(int u) {
    
    
        while (s[pos - len[u] - 1] != s[pos]) {
    
    
            u = fail[u];
        }
        return u;
    }

    void extend(char c) {
    
    
        s[++pos] = c;
        int d = c - 'a';
        int u = jump(las);
        if (!ch[u][d]) {
    
    
            int v = node(len[u] + 2);
            fail[v] = ch[jump(fail[u])][d];
            ch[u][d] = v;
        }
        las = ch[u][d];
        cnt[las]++;
    }
} pam;

char s[PAMN];
int arr[PAMN][26];


int main() {
    
    
    pam.init();
    scanf("%s", s + 1);
    int n = strlen(s + 1);
    for (int i = 1; i <= n; i++) {
    
    
        pam.extend(s[i]);
    }

    ll ans = 0;

    for (int i = pam.tot; i > 1; i--) {
    
    
        pam.cnt[pam.fail[i]] += pam.cnt[i];
    }

    for (int i = 1; i <= n; ++i) {
    
    
        memcpy(arr[i], arr[i - 1], sizeof arr[0]);
        arr[i][s[i] - 'a']++;
    }

    for (int i = 2, l, r; i <= pam.tot; i++) {
    
    
        ll tmp = 0;
        r = pam.npos[i];
        l = r - pam.len[i];
        for (int j = 0; j < 26; ++j) {
    
    
            tmp += ll(arr[l][j] < arr[r][j]);
        }
        ans += tmp * pam.cnt[i];
    }

    printf("%lld\n", ans);
    return 0;
}

Guess you like

Origin blog.csdn.net/Tighway/article/details/108654496