7.28SAM后缀自动机,回文自动机

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 20 ; 
struct SAM{
    int t[N][26] , link[N] , len[N];
    int last ,tot ; 
    SAM() : last(1) , tot(1){}
    void insert(int c){
        int p = last , np = last = ++tot ; //p是之前的节点 np是现新建的节点
        len[np] = len[p] + 1 ; //首先会多一个endpos为n的,其他的不可能和他重复
        while( p and !t[p][c] )t[p][c] = np , p = link[p];//link[p]相当于fail指针 向上跳使得s -> s的后缀 在后缀上->一个 就相当于是一个新的子串
        if(!p)link[np] = 1 ;//如果跳到根了,说明没有与他相同的子串,所以失配只能跳到根
        else{//如果有和他一样的子串
            int q = t[p][c] ; 
            if( len[q] == len[p] + 1)link[np] = q ;//如果说是s+c的等价后继类是s的等价类最长的+1 ,那么他就是等价后继类
            else{
                int nq = ++tot ; 
                memcpy( t[nq] , t[q] , sizeof(t[q]));//转移函数不变
                len[nq] = len[p] + 1 ; //新加了一个c所以长度+1
                link[nq] = link[q] ;//
                /*如图
                    nq
                   /  \
                  q    np 
                */
                link[np] = link[q] = nq ;//
                while( p and t[p][c] == q )t[p][c] = nq , p = link[p];//更新其他的到他的节点
            }
        }
    }
}
posted @ 2025-07-28 20:25  Nailong2357  阅读(19)  评论(1)    收藏  举报