回文树(模板)+ 例题

回文树是一种处理回文串问题的高效工具。它能够实现求解字符串前缀内的回文串个数、回文串出现次数等功能。文章通过提供例题1至例题3,展示了回文树在解决不同场景下的应用,如BZOJ3676中求字符串回文子串出现次数与长度乘积的最大值,UVA7041中计算相同回文子串的个数总和,以及在动态操作字符串时计算回文串个数的问题。
摘要由CSDN通过智能技术生成

引用:
Palindromic Tree——回文树【处理一类回文串问题的强力工具】
回文树练习题集

首先,回文树有何功能?
假设我们有一个串S,S下标从0开始,则回文树能做到如下几点:

1.求串S前缀0~i内本质不同回文串的个数(两个串长度不同或者长度相同且至少有一个字符不同便是本质不同)
2.求串S内每一个本质不同回文串出现的次数
3.求串S内回文串的个数(其实就是1和2结合起来)
4.求以下标i结尾的回文串的个数

模板:

const int MAXN = 100005 ;  
const int N = 26 ;  

struct Palindromic_Tree {  
    int next[MAXN][N] ;//next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成  
    int fail[MAXN] ;//fail指针,失配后跳转到fail指针指向的节点  
    int cnt[MAXN] ; //表示节点i表示的本质不同的串的个数(建树时求出的不是完全的,最后count()函数跑一遍以后才是正确的) 
    int num[MAXN] ; //表示以节点i表示的最长回文串的最右端点为回文串结尾的回文串个数
    int len[MAXN] ;//len[i]表示节点i表示的回文串的长度(一个节点表示一个回文串)
    int S[MAXN] ;//存放添加的字符  
    int last ;//指向新添加一个字母后所形成的最长回文串表示的节点。
    int n ;//表示添加的字符个数。
    int p ;//表示添加的节点个数。

    int newnode ( int l ) {
  //新建节点  
        for ( int i = 0 ; i < N ; ++ i ) next[p][i] = 0 ;  
        cnt[p] = 0 ;  
        num[p] = 0 ;  
        len[p] = l ;  
        return p ++ ;  
    }  

    void init () {
  //初始化  
        p = 0 ;  
        newnode (  0 ) ;  
        newnode ( -1 ) ;  
        last = 0 ;  
        n = 0 ;  
        S[n] = -1 ;//开头放一个字符集中没有的字符,减少特判  
        fail[0] = 1 ;  
    }  

    int get_fail ( int x ) {
  //和KMP一样,失配后找一个尽量最长的  
        while ( S[n - len[x] - 1] != S[n] ) x = fail[x] ;  
        return x ;  
    }  

    void add ( int c ) {  
        c -= 'a' ;  
        S[++ n] = c ;  
        int cur = get_fail ( last ) ;//通过上一个回文串找这个回文串的匹配位置  
        if ( !next[cur][c] ) {
  //如果这个回文串没有出现过,说明出现了一个新的本质不同的回文串  
            int now = newnode ( len[cur] + 2 ) ;//新建节点  
            fail[now] = next[get_fail ( 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值