bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp)

bzoj Luogu

对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串。比如00001111和010101就是反对称的,1001就不是。

现在给出一个长度为N的01字符串,求它有多少个子串是反对称的。

题解时间

这玩意咋看都像是回文串不是嘛。

然后与此同时还是经典计数问题。

所以考虑能不能以这里面的这个规则写个PAM

发现还真能搞:

首先这种串只有偶串,所以不建奇方向的(跳到奇根1直接跳出)

此外再把match改一下

完事了。

#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
namespace RKK
{
const int N=500011;
char str[N];int n;
struct remilia{int tranc[2],len,fail;};
struct sakuya
{
    remilia p[N];
    int fin,size;
    int val[N];
    sakuya()
    {
        fin=0,size=1;
        p[0].len=0,p[1].len=-1;
        p[0].fail=p[1].fail=1;
    }
    int match(char *s,int i,int px){return p[px].len==-1||(i-p[px].len-1!=0&&s[i-p[px].len-1]!=s[i]);}
    void ins(char *s,int i)
    {
        int ch=s[i]-'0';
        int npx,lpx,lpy;
        lpx=fin;
        while(!match(s,i,lpx)) lpx=p[lpx].fail;
        if(i-p[lpx].len-1==0||s[i-p[lpx].len-1]==s[i]){fin=0;return;}
        if(!p[lpx].tranc[ch])
        {
            npx=++size;
            p[npx].len=p[lpx].len+2;
            lpy=p[lpx].fail;
            while(!match(s,i,lpy)) lpy=p[lpy].fail;
            p[npx].fail=p[lpy].tranc[ch];
            p[lpx].tranc[ch]=npx;
        }
        fin=p[lpx].tranc[ch];
        val[fin]++;
    }
    void work()
    {
        lint ans=0;
        for(int i=size;i>=2;i--) val[p[i].fail]+=val[i],ans+=val[i];
        printf("%lld\n",ans);
    }
}pam;
int Iris()
{
    scanf("%d%s",&n,str+1);
    for(int i=1;i<=n;i++) pam.ins(str,i);
    pam.work();
    return 0;
}
}
int main(){return RKK::Iris();}

原文地址:https://www.cnblogs.com/rikurika/p/12079220.html

时间: 2024-11-05 22:52:13

bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp)的相关文章

bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp)

bzoj Luogu 你要用ATGC四个字母用两种操作拼出给定的串: 1.将其中一个字符放在已有串开头或者结尾. 2.将已有串复制,然后reverse,再接在已有串的头部或者尾部. 一开始已有串为空.求最少操作次数. len<=100000 题解时间 一个非空串经过一次操作2之后一定是一个偶回文串. 所以考虑建出PAM之后dp. 由于只有偶回文串可以通过操作2产生,所以只有偶回文串参与dp. 对于PAM上一个点 $ x $ : 如果这个串去掉两头一个字母之后的串 $ y $ 非空,那么很明显 $

[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

[加强版] Codeforces 835D Palindromic characteristics (回文自动机、DP)

题目链接: https://codeforces.com/contest/835/problem/D 题意: 一个回文串是\(1\)-回文的,如果一个回文串的左半部分和右半部分一样且都是\(k\)-回文串(右半部分是指长度为该串长度除以二下取整的后缀),则该串为\((k+1)\)回文串,满足该串是\(k\)回文串的最大\(k\)称作该串的回文级别.给定一个串\(s\), 对于每一个\(k=1,2,...,n\)求出该串中有多少个位置不同的\(k\)-回文串.\(n\le 5\times 10^6

【回文自动机】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

回文自动机刷题总结

最长双回文串 裸的回文自动机,将串reverse再插入一遍即可. 双倍回文 这题可以只维护偶回文串然后疯狂加特判判掉奇串 回文自动机,再多维护一个trans指针,指向trans[x]表示长度小于len[x]/2的最长的回文后缀 trans指针可以从父亲(不是fail)的trans指针求出. 其实还可以直接建完自动机后在fail树(即把fail指针当作父亲边构成的树)上开桶dfs 1 #include<bits/stdc++.h> 2 #define N 500050 3 using names

「专题总结」回文自动机PAM

为了备课,把做完的专题的总结咕了这么久... 主要是自己做题做的太慢了,所以讲SAM的时候准备也不充分. 在把讲课时间不断咕之后依然是粗制滥造,锅很多,所以效果很差.而且还有人没听懂... 一半人都做了5道题以上了,另一半人还没怎么看,基本所有人都有预习. 得不到任何反馈,也不知道速度如何.就当凑活吧. 挺失败的.可能也没有下一次机会了. 我也不知道后缀数组推荐率是怎么达到100%的...那次我讲的自己也很满意 一到难的知识点我就不行了嘛...主要是自己理解也很不深刻 至少也还是在3个多小时之内

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

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

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

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

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

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