C++回文自动机

算法原理

  1. 节点结构

    • 每个节点代表一个回文子串。

    • 包含长度 len、失败指针 fail 和子节点转移 trans

  2. 双根结构

    • 偶根(0号节点):长度为0,处理偶数长度回文。

    • 奇根(1号节点):长度为-1,处理奇数长度回文。

  3. 构建过程

    • 逐个字符处理,维护当前最长回文后缀节点 last

    • 对于新字符,沿 last 的失败链找到可扩展的节点,创建新节点并更新指针。

  4. 失败指针

    • 类似AC自动机,用于在无法扩展时跳转到其他回文后缀。

C++实现

#include 
#include 
#include 
using namespace std;

const int MAXN = 1e5 + 5;

struct PAM {
    int len[MAXN], fail[MAXN], trans[MAXN][26];
    int size, last;
    string s;

    PAM() {
        len[0] = 0; len[1] = -1;   // 初始化偶根和奇根
        fail[0] = 1; fail[1] = 1;  // 失败指针初始指向奇根
        memset(trans, 0, sizeof(trans));
        size = 2;                  // 已包含两个根节点
        last = 0;                  // 初始指向偶根
        s.clear();
    }

    // 辅助函数:寻找可扩展的失败指针
    int get_fail(int x) {
        // 沿着失败链找到满足前后字符相同的位置
        while (s.size() - len[x] - 2 < 0 || s[s.size() - len[x] - 2] != s.back()) {
            x = fail[x];
        }
        return x;
    }

    // 添加字符并更新自动机
    void add(char c) {
        s += c; // 将字符添加到字符串末尾
        int now = get_fail(last); // 找到可扩展的节点
        int ch = c - 'a';
        
        if (!trans[now][ch]) { // 新建节点
            int node = size++;
            len[node] = len[now] + 2; // 新回文长度
            
            // 设置失败指针
            if (len[node] == 1) { // 单字符回文指向偶根
                fail[node] = 0;
            } else {
                // 寻找失败路径并设置
                int tmp = get_fail(fail[now]);
                fail[node] = trans[tmp][ch];
            }
            trans[now][ch] = node; // 记录转移
        }
        last = trans[now][ch]; // 更新当前最长回文后缀
    }
};

int main() {
    PAM pam;
    string s = "abba";
    for (char c : s) {
        pam.add(c);
        cout << "添加字符 '" << c << "' 后,最长回文后缀节点: " 
             << pam.last << " (长度: " << pam.len[pam.last] << ")\n";
    }
    return 0;
}

解释:

  1. 初始化:偶根和奇根构成初始结构,fail[0] 指向奇根。

  2. 添加字符

    • 通过 get_fail 找到可扩展的位置 now

    • 若 trans[now][ch] 不存在,则创建新节点,计算长度并设置失败指针。

  3. 失败指针设置

    • 单字符回文直接指向偶根。

    • 多字符回文则沿失败链找到匹配位置。

你可能感兴趣的:(c++,算法)