算法学习:回文自动机

【定义】

【自动机】

参照AC自动机



【前置知识】

【AC自动机】

【manacher】

其实不学这两个也可以,但是学过之后会更方便理解



【解决问题】

主要解决回文串的问题

能求出   字符串中回文子串的长度和出现次数



#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#define ll long long
using namespace std;
const int mod = 19930726;
const int MAXN = 1000010;
ll k;
int n, cnt;
int now;
struct note
{
    int son[26];
    ll len;
    int  siz;
}trie[MAXN];
int fail[MAXN], pos;
bool operator<(note a, note b)
{
    return a.len > b.len;
}
char s[MAXN];
int get(int x)
{
    while (s[pos] != s[pos - trie[x].len - 1]) x = fail[x];
    return x;
}
void insert(int x)
{
    int cur = get(now);
    if (!trie[cur].son[x])
    {
        int u = ++cnt;
        trie[u].len = trie[cur].len + 2;
        fail[u] = trie[get(fail[cur])].son[x];
        trie[cur].son[x] = u;
    }
    trie[trie[cur].son[x]].siz++;
    now = trie[cur].son[x];
}
ll poww(ll a, int b)
{
    ll res = 1;
    while (b)
    {
        if (b & 1)
        {
            res = (res*a) % mod;
        }
        a = (a*a) % mod;
        b = b >> 1;
    }
    return res;
}
void init()
{
    fail[0] = 1; fail[1] = 0;
    now = 0, cnt = 1;
    trie[1].len = -1;
}
int main()
{
    scanf("%d%lld", &n, &k);
    scanf("%s", s+1);
    init();
    s[0] = 0;
    for (pos = 1; pos <= n; pos++)
        insert(s[pos] - ‘a‘);

    for (int i = cnt; i >= 2; i--)
        trie[fail[i]].siz = (trie[fail[i]].siz + trie[i].siz) % mod;
    //for (int i = 1; i <= cnt; i++)
        //printf("%lld %d\n", trie[i].len, trie[i].siz);
    sort(trie + 1, trie + 1 + cnt);
    ll ans = 1;
    int pos = 1;
    while (k)
    {
        if (pos > cnt)
        {
            printf("-1");
            return 0;
        }
        if (trie[pos].len % 2 == 0)
        {
            pos++;
            continue;
        }
        ans = (ans*poww(trie[pos].len, k < trie[pos].siz ? k : trie[pos].siz)) % mod;
        k -= k < trie[pos].siz ? k : trie[pos].siz;
        pos++;
    }
    printf("%lld", ans);
    return 0;
}

原文地址:https://www.cnblogs.com/rentu/p/11305837.html

时间: 2024-10-11 06:59:34

算法学习:回文自动机的相关文章

算法学习:后缀自动机

[前置知识] AC自动机(没有什么关联,但是看懂了会对后缀自动机有不同的理解) [解决问题] 各种子串的问题 [算法学习] 学习后缀自动机的过程中,看到了许多相关性质和证明,但是奈何才疏学浅(lan) 暂时先放着,到有空再更 [算法分析] 后缀自动机和AC自动机和回文自动机的不同点在于 后缀自动机是个DAG,而AC自动机和回文自动机是树 首先理解   endpos 数组,每个子串都有一个endpos数组,表示他在字符串中出现的位置的结束位置 而endpos数组相同的子串,就被称为endpos类

回文树或者回文自动机,及相关例题

回文树简述 在大部分说法中,回文树与回文自动机指的是一个东西: 回文树是对一个字符串,基于自动机思想构建的处理回文问题的树形结构: 回文树是对着一个单串建立的: 于是他主要用于计数(回文子串种类及个数) 基本建立思路是先建立其前缀的回文树,然后每加上一个字符,统计影响: 回文树存在fail指针但一般不承接字符串匹配问题: (回文树大概可以判定一个回文串是不是一个串的子串,但KMP之类的可以做得更好) 构建好的回文树,是这样的: (好难看) 可看出: 存在两个树结构,分别记录奇数|偶数长度的回文:

Palindromic Tree 回文自动机-回文树 例题+讲解

---恢复内容开始--- 回文树,也叫回文自动机,是2014年被西伯利亚民族发明的,其功能如下: 1.求前缀字符串中的本质不同的回文串种类 2.求每个本质不同回文串的个数 3.以下标i为结尾的回文串个数/种类 4.每个本质不同回文串包含的本质不同回文串种类 (本文参考自Palindromic Tree——回文树[处理一类回文串问题的强力工具],Palindromic Tree 回文自动机-回文树 解决回文串的神器) 下面介绍一些数组的意义 next[][]类似于字典树,指向当前字符串在两段同时加

【CF932G】Palindrome Partition 回文自动机

[CF932G]Palindrome Partition 题意:给你一个字符串s,问你有多少种方式,可以将s分割成k个子串,设k个子串是$x_1x_2...x_k$,满足$x_1=x_k,x_2=x_{k-1}...x_i=x{k-i+1}$. $|s|\le 10^6$ 题解:设字符串的长度为n,考虑字符串$T=s_1s_ns_2s_{n-1}...$.问题就转化成了:求将原串划分成若干个长度为偶数的回文子串的方案数. 首先我们有一种暴力的想法,设f[i]表示将前i个字符分成若干个回文子串的方

回文自动机例题

今天学习了一下回文自动机,吊打\(manacher\)有没有(除了空间) 回文自动机基于这两个性质: 1.一个长度为\(n\)的字符串的本质不同回文子串是\(O(n)\)级别的 2.在一个字符串后增加一个字符后,最多新增\(1\)个本质不同回文子串 这两条性质都可以用归纳法证明 于是我们想到用一个结点来代表一个本质不同的回文串,然后就有\(PAM\)了.和\(AC\)自动机一样,\(PAM\)也有\(fail\)失配边和\(ch\)转移边,\(fail\)代表的是最长回文后缀 采用增量构造法来构

【回文自动机】bzoj3676 [Apio2014]回文串

回文自动机讲解!http://blog.csdn.net/u013368721/article/details/42100363 pam上每个点代表本质不同的回文子串.len(i)代表长度,cnt(i)代表个数(要最后在fail树上dp一遍方可). 答案直接枚举一遍结点,然后用len(i)*cnt(i),取最大者即可. 回文自动机是非常优越的数据结构,可惜比manacher多一个字符集的空间-- #include<cstdio> #include<cstring> #include

【bzoj3676】[Apio2014]回文串 回文自动机

题目描述 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最大出现值. 输入 输入只有一行,为一个只包含小写字母(a -z)的非空字符串s. 输出 输出一个整数,为逝查回文子串的最大出现值. 样例输入 [样例输入l] abacaba [样例输入2] www 样例输出 [样例输出l] 7 [样例输出2] 4 题解 回文自动机裸题 关于PAM个人暂时理解不是很深入,挖坑待填. 本题只需要统计fail树的子树大小,再

[BZOJ4044]Virus synthesis 回文自动机的DP

4044: [Cerc2014] Virus synthesis Time Limit: 20 Sec  Memory Limit: 128 MB Description Viruses are usually bad for your health. How about fighting them with... other viruses? In this problem, you need to find out how to synthesize such good viruses. W

HDU 5371(2015多校7)-Hotaru&#39;s problem(Manacher算法求回文串)

题目地址:HDU 5371 题意:给你一个具有n个元素的整数序列,问你是否存在这样一个子序列,该子序列分为三部分,第一部分与第三部分相同,第一部分与第二部分对称,如果存在求最长的符合这种条件的序列. 思路:用Manacher算法来处理回文串的长度,记录下以每一个-1(Manacher算法的插入)为中心的最大回文串的长度.然后从最大的开始穷举,只要p[i]-1即能得出以数字为中心的最大回文串的长度,然后找到右边对应的'-1',判断p[i]是不是大于所穷举的长度,如果当前的满足三段,那么就跳出,继续

【XSY2715】回文串 树链剖分 回文自动机

题目描述 有一个字符串\(s\),长度为\(n\).有\(m\)个操作: \(addl ~c\):在\(s\)左边加上一个字符\(c\) \(addr~c\):在\(s\)右边加上一个字符 \(transl~l_1~r_1~l_2~r_2\):有两个\(s\)的子串\(s_1=s[l_1\ldots r_1],s_2=s[l_2\ldots r_2]\).你要把\(s_1\)变成\(s_2\).每次允许在左边加一个字符或删一个字符.要求操作次数最少.定义一个字符串是好的当且仅当这个字符串是回文串