WHU 583 Palindrome ( 回文自动机 && 本质不同的回文串的个数 )
题意 : 给你一个串、要你将其划分成两个串、使得左边的串的本质不同回文子串的个数是右边串的两倍、对于每一个这样子的划分、其对答案的贡献就是左边串的长度、现在要你找出所有这样子的划分、并将贡献乘起来、答案 mod 1e9+7
分析 :
从左到右跑一边回文自动机、对于每个前缀
能够得出其有多少个本质不同的回文子串
本质不同的回文子串的个数实际上就是自动机节点数 - 2
那么跑一遍前缀之后我们能得到所有可作为左边部分串的本质不同回文子串的个数
因为是回文串、所以我们倒着跑一遍、就同样能得到作为右边部分串的本质不同回文子串的个数
最后暴力检查一遍对于每一个位置是否有符合题意的合理划分、如果有就将左边部分长度累乘起来
#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)
#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))
#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>
#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;
struct Palindromic_Tree {
;
;
deque<int> text;
int len[maxn];///len[i]表示节点i表示的回文串的长度
int cnt[maxn];///第 i 节点表示的回文串出现的次数、注意最后调用 getCnt 函数完成计算
int num[maxn];///表示以节点 i 代表的回文串端点为端点的不同回文串个数
int nxt[maxn][Letter];///nxt静态指针和字典树类似,指向的串为当前串两端加上同一个字符构成
int fail[maxn];///失配指针
int odd, even;///奇偶原始节点
int pre, suf;
int totNode;///自动机所有节点的个数
LL totNum;///串中所有回文串数量
int newNode(int _len){
int ret = totNode++;
len[ret] = _len;
cnt[ret] = num[ret] = ;
fail[ret] = ;
memset(nxt[ret], , sizeof(nxt[ret]));
return ret;
}
inline void init(){
text.clear();
totNode = ;
totNum = ;
even = newNode();
odd = newNode(-);
fail[even] = fail[odd] = odd;
pre = suf = even;
}
int encode(char c){
return c - 'a';
}
template<typename FunT>
int getFail(int ch, int cur, FunT getNext){
for(int i = getNext(len[cur]);
i < || i >= (int)text.size() || text[i] != ch;
cur = fail[cur], i = getNext(len[cur]));
return cur;
}
template<typename FunT>
int Insert(int ch, int last, FunT getNext){
last = getFail(ch, last, getNext);
if(!nxt[last][ch]){
);
fail[cur] = nxt[getFail(ch, fail[last], getNext)][ch];
nxt[last][ch] = cur;
num[cur] = num[fail[cur]] + ;
}
last = nxt[last][ch];
totNum += (LL)num[last];
cnt[last]++;
return last;
}
int push_front(char c){
text.push_front(encode(c));
pre = Insert(encode(c), pre, [](; });
if(len[pre] == (int)text.size()) suf = pre;
return totNode;
}
int push_back(char c){
text.push_back(encode(c));
suf = Insert(encode(c), suf, [; });
if(len[suf] == (int)text.size()) pre = suf;
return totNode;
}
int push_front(char *s){
;
; s[i]; i++)
ret = push_front(s[i]);
return ret;
}
int push_back(char *s){
;
; s[i]; i++)
ret = push_back(s[i]);
return ret;
}
inline void getCnt(){
; i>=; i--)
cnt[fail[i]] += cnt[i];
}
}PAM1, PAM2;
;
;
char str[maxn];
LL L[maxn], R[maxn];
int main(void){__stTIME();__IOPUT();
int T;
sci(T);
while(T--){
mem(L, );
mem(R, );
PAM1.init();
PAM2.init();
scs(str);
int len = strlen(str);
; i<len; i++){
PAM1.push_back(str[i]);
L[i] = PAM1.totNode - ;
}
; i>=; i--){
PAM2.push_back(str[i]);
R[i] = PAM2.totNode - ;
}
LL ans = ;
; i<len; i++){
* R[i+]){
) ans = 1LL;
ans = (1LL * (i+) * ans) % mod;
}
}
printf("%lld\n", ans);
}
__enTIME();;}
void __stTIME()
{
#if _TIME
START = clock();
#endif
}
void __enTIME()
{
#if _TIME
END = clock();
cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
#endif
}
void __IOPUT()
{
#if _INPUT
freopen("in.txt", "r", stdin);
#endif
#if _OUTPUT
freopen("out.txt", "w", stdout);
#endif
}
WHU 583 Palindrome ( 回文自动机 && 本质不同的回文串的个数 )的更多相关文章
- 【回文自动机】bzoj3676 [Apio2014]回文串
回文自动机讲解!http://blog.csdn.net/u013368721/article/details/42100363 pam上每个点代表本质不同的回文子串.len(i)代表长度,cnt(i ...
- hdu多校第二场1009 (hdu6599) I Love Palindrome String 回文自动机/字符串hash
题意: 找出这样的回文子串的个数:它本身是一个回文串,它的前一半也是一个回文串 输出格式要求输出l个数字,分别代表长度为1~l的这样的回文串的个数 题解: (回文自动机和回文树是一个东西) 首先用回文 ...
- 洛谷P5496 回文自动机【PAM】模板
回文自动机模板 1.一个串的本质不同的回文串数量是\(O(n)\)级别的 2.回文自动机的状态数不超过串长,且状态数等于本质不同的回文串数量,除了奇偶两个根节点 3.如何统计所有回文串的数量,类似后缀 ...
- bzoj千题计划306:bzoj2342: [Shoi2011]双倍回文 (回文自动机)
https://www.lydsy.com/JudgeOnline/problem.php?id=2342 解法一: 对原串构建回文自动机 抽离fail树,从根开始dfs 设len[x]表示节点x表示 ...
- [BZOJ4044]Virus synthesis 回文自动机的DP
4044: [Cerc2014] Virus synthesis Time Limit: 20 Sec Memory Limit: 128 MB Description Viruses are us ...
- bzoj 2084: Antisymmetry 回文自动机
题目: Description 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作"反对称"字符串.比如00001111和010101就是反对称的 ...
- 【CF932G】Palindrome Partition 回文自动机
[CF932G]Palindrome Partition 题意:给你一个字符串s,问你有多少种方式,可以将s分割成k个子串,设k个子串是$x_1x_2...x_k$,满足$x_1=x_k,x_2=x_ ...
- 2019牛客暑期多校训练营(第六场)C - Palindrome Mouse (回文自动机)
https://ac.nowcoder.com/acm/contest/886/C 题意: 给出一个串A , 集合S里面为A串的回文字串 , 现在在集合S里面找出多少对(a,b),b为a的字串 分析: ...
- HDU-6599 I Love Palindrome String(回文自动机+字符串hash)
题目链接 题意:给定一个字符串\(|S|\le 3\times 10^5\) 对于每个 \(i\in [1,|S|]\) 求有多少子串\(s_ls_{l+1}\cdots s_r\)满足下面条件 \( ...
随机推荐
- Python3 + selenium + Chrome浏览器(webdriver.Chrome()报错)
Python3 + selenium + Chrome浏览器 Error: selenium.common.exceptions.WebDriverException: Message: 'chrom ...
- 第一章 MIZ701 VIVADO 搭建SOC最小系统HelloWorld
本章内容是MIZ701中的第五章,本来也是要过渡一下FPGA部分的,但是由于MIZ701没有单独提供PL部分的晶振时钟,时钟必须通过PS产生,所以本章内容作为Miz701的第一章内容.本章的目的是 ...
- java学习要想精炼掌握应运的必备知识(博文来源于网络)
一: 编程基础 不管是C还是C++,不管是Java还是PHP,想成为一名合格的程序员,基本的数据结构和算法基础还是要有的.下面几篇文章从思想到实现,为你梳理出常用的数据结构和经典算法. 1-1 常用数 ...
- 牛客 128A 礼物 (组合计数)
大意: n种一元的奥利奥, m种2元的奥利奥, 求花恰好k元钱购买奥利奥的方案数. 可重组合问题, 直接dp即可. #include <iostream> #include <sst ...
- 我的第一个python web开发框架(2)——第一个Hello World
小白中午听完老菜讲的那些话后一直在思考,可想来想去还是一头雾水,晕晕呼呼的一知半解,到最后还是想不明白,心想:老大讲的太高深了,只能听懂一半半,看来只能先记下来,将明白的先做,不明白的等以后遇到再学. ...
- Lua虚拟机中的数据结构与栈
Lua虚拟机中的数据结构与栈 来源 https://blog.csdn.net/zry112233/article/details/80828327 由上一篇文章可知解释器分析Lua文件之后生成Pro ...
- luogu1018乘积最大--区间DP
题目链接 https://www.luogu.org/problemnew/show/P1018 分析 这道题套路跟山区建小学差不多,可以先去看看那篇题解 \(f[i][j]\)表示枚举到第\(i\) ...
- redis 命令行操作报错
向redis集群写数据抛异常:(error) MOVED 15342 2001:fecc:0:616::34:6383 原因是启动redis-cli时未以集群方式启动,即后面要加上 -c redis- ...
- 关于spring中事务管理的几件小事
1.Spring中的事务管理 作为企业级应用程序框架,Spring在不同的事务管理API之上定义了一个抽象层.而应用程序开发人员不必了解底层的事务管理API,就可以使用Spring的事务管理机制. S ...
- HTML给标题栏添加图标
<link rel="icon" href="images/logo.icon" type="image/x-icon"> 也可 ...