字符串算法【模板】

学习博客:

字符串哈希:https://blog.csdn.net/pengwill97/article/details/80879387      (好像求区间有点小问题)

马拉车Manacher:  https://blog.csdn.net/Clove_unique/article/details/53750322

回文自动机/回文树:
https://blog.csdn.net/Clove_unique/article/details/53750322
https://ksmeow.moe/palindromic_tree/
https://www.cnblogs.com/bztMinamoto/p/9630617.html
https://www.cnblogs.com/nietzsche-oier/p/6935081.html

模板题练习:

字符串哈希:P3370 【模板】字符串哈希

马拉车Manacher:POJ 3974 Palindrome

回文自动机:P3649 [APIO2014]回文串

模板:

Manacher:

int d, len, c, r, ansc, ansr, p[maxn<<1];
///r-1是最大回文串能到达的最右端的值
char x[maxn], m[maxn<<1];
void manacher() {
    c = r = ansc = ansr = 0;
    len = strlen(x + 1);
    d = len * 2 + 1, m[0] = '@', m[1] = '#';
    for(int i = 1; i <= len; i++)
        m[i * 2] = x[i], m[i * 2 + 1] = '#';
    m[d + 1] = '\0';
    for(int i = 1; i <= d; i++) {
        p[i] = r > i ? min(p[2 * c - i], r - i) : 1;
        while(m[i + p[i]] == m[i - p[i]])
            p[i]++;
        if(r < i + p[i])
            c = i, r = i + p[i];
        if(ansr < p[i])
            ansr = p[i], ansc = i;
    }
}

回文自动机:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 5;
char s[maxn];
struct PAM {
    int d, last;
    ///d为建立回文自动机的字符串长度
    ///last上一次插入字符串停在的节点
    struct Node {
        int cnt, len, fail, child[27];
        Node(int len, int fail): len(len), fail(fail), cnt(0) {
            memset(child, 0, sizeof(child));
        };
    };
    vector<Node>st;
    inline int newnode(int len, int fail = 0) {
        ///新建一个点
        st.emplace_back(len, fail);
        return st.size() - 1;
    }
    inline int getfail(int x, int n) {
        ///x为当前点的编号,n为插入字符的位置
        while(s[n] != s[n - st[x].len - 1])
            x = st[x].fail;
        return x;
    }
    inline void Insert(int i) {
        int c = s[i] - 'a';
        int cur = getfail(last, i);
        ///不存在这条边,新增节点
        if(!st[cur].child[c]) {
            int p = newnode(st[cur].len + 2, st[getfail(st[cur].fail, i)].child[c]);
            st[cur].child[c] = p;
        }
        ///更新last,数量+1
        st[last = st[cur].child[c]].cnt++;
    }
    void init(char *s) {
        st.clear();
        d = strlen(s + 1);
        s[0] = 0;
        ///建立偶串和奇串的根和fail
        /// 偶的fail->奇
        newnode(0, 1), newnode(-1);
        last = 0;
        for(int i = 1; i <= d; i++)
            Insert(i);
    }
    long long get_all() {
        long long ans = 0;
        for(int i = st.size() - 1; i >= 0; i--)
            st[st[i].fail].cnt += st[i].cnt;
        for(int i = 2; i < st.size(); i++)
            ans = max(ans, 1LL * st[i].len * st[i].cnt);
        return ans;
    }
} pam;
int main() {
    scanf("%s", s + 1);
    pam.init(s);
    printf("%lld\n", pam.get_all());
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值