2019牛客暑期多校训练营(第六场)C - Palindrome Mouse (回文自动机)
https://ac.nowcoder.com/acm/contest/886/C
题意: 给出一个串A , 集合S里面为A串的回文字串 , 现在在集合S里面找出多少对(a,b),b为a的字串
分析:回文字串嘛,先盲猜一波回文自动机:我们现在知道回文自动机的原理图可以得出 , 它其实是用两棵树顶点为0和1
假设现在对于一个 XXXabccbaXXX 现在对于查到的点a 的贡献 , 我们发现是说它向外的层数*向内的层数-1 ,比如现在a向外3层,向内2层,包括a.....a的答案有2*3-1种 , -1是减去本身因为不可能选到 abccba , abccba 嘛,一个就一个(这个意思不能选本身两次)
然后向外层数直接 fail 向上去找 , 向下就用next 去找
#include <bits/stdc++.h>
using namespace std; const int MAXN = ;
const int N = ;
typedef long long LL;
struct Palindromic_Tree {
int next[MAXN][N] ;//next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成
int fail[MAXN] ;//fail指针,失配后跳转到fail指针指向的节点
LL cnt[MAXN] ; //表示节点i表示的本质不同的串的个数(建树时求出的不是完全的,最后count()函数跑一遍以后才是正确的)
int num[MAXN] ; //表示以节点i表示的最长回文串的最右端点为回文串结尾的回文串个数
int len[MAXN] ;//len[i]表示节点i表示的回文串的长度(一个节点表示一个回文串)
int S[MAXN] ;//存放添加的字符
int last ;//指向新添加一个字母后所形成的最长回文串表示的节点。
int n ;//表示添加的字符个数。
int p ;//表示添加的节点个数。
LL up[MAXN],down[MAXN];
bool vis[MAXN];
int newnode ( int l ) {//新建节点
for ( int i = ; i < N ; ++ i ) next[p][i] = ;
cnt[p] = ;
num[p] = ;
len[p] = l ;
return p ++ ;
} void init () {//初始化
p = ;
newnode ( ) ;
newnode ( - ) ;
last = ;
n = ;
S[n] = - ;//开头放一个字符集中没有的字符,减少特判
fail[] = ;
} int get_fail ( int x ) {//和KMP一样,失配后找一个尽量最长的
while ( S[n - len[x] - ] != 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] + ) ;//新建节点
fail[now] = next[get_fail ( fail[cur] )][c] ;//和AC自动机一样建立fail指针,以便失配后跳转
next[cur][c] = now ;
num[now] = num[fail[now]] + ;
}
last = next[cur][c] ;
cnt[last] ++ ;
} void count () {
for ( int i = p - ; i >= ; -- i ) cnt[fail[i]] += cnt[i] ;
//父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串!
}
int dfs(int rt){
up[rt]=;
vector<int> A;
for(int i=rt ; i> ; i=fail[i])
{
if(vis[i]!=) break;
vis[i]=rt;
A.push_back(i);
up[rt]++;///统计向外有多少
}
down[rt]=;
for(int i= ; i< ; i++)
{
if(next[rt][i]==) continue;
down[rt]+=dfs(next[rt][i]);///统计向下有多少
}
for(int i=A.size()-;i>=;i--)
vis[A[i]]=;
return down[rt]; }
LL solve(){
LL ans=;
dfs();///偶数长度
dfs();///奇数长度
for(int i= ; i<p ; i++)
ans+=down[i]*up[i]; ///当前的价值等于我可以向外多少*向内多少
return ans-(p-);///减去本身的顶点数(去重复)
}
}Tree; char a[MAXN];
int main()
{ int t;
int ct=;
scanf("%d",&t);
while(t--)
{
scanf("%s",a);
Tree.init();
int len=strlen(a);
for(int i=;i<len;i++)
Tree.add(a[i]);
printf("Case #%d: ",ct++);
printf("%lld\n",Tree.solve());
}
}
2019牛客暑期多校训练营(第六场)C - Palindrome Mouse (回文自动机)的更多相关文章
- 2019牛客暑期多校训练营(第六场)J Upgrading Technology
		传送门 题意: 就是给你n个技能,每个技能最高升到m级,每升一级就是耗费Cij钱,这个Cij可能是负的,如果所有技能都升到或者说超过j等级,就会获得Dj钱,这个Dj也有可能是负值,让你求你最多得到多少 ... 
- 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)
		题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9: 对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可. 后者mod=1e9,5才 ... 
- 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)
		链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ... 
- 2019牛客暑期多校训练营(第一场) B	Integration (数学)
		链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ... 
- 2019牛客暑期多校训练营(第一场) A	Equivalent Prefixes ( st 表 + 二分+分治)
		链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ... 
- 2019牛客暑期多校训练营(第二场)F.Partition problem
		链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ... 
- 2019牛客暑期多校训练营(第一场)A	Equivalent Prefixes(单调栈/二分+分治)
		链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ... 
- [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem
		链接:https://ac.nowcoder.com/acm/contest/889/D来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ... 
- 2019牛客暑期多校训练营(第二场)J-Subarray(思维)
		>传送门< 前言 这题我前前后后看了三遍,每次都是把网上相关的博客和通过代码认真看了再思考,然并卵,最后终于第三遍也就是现在终于看懂了,其实懂了之后发现其实没有那么难,但是的的确确需要思维 ... 
随机推荐
- python 正则表达式 re.findall &re.finditer
			语法: findall 搜索string,以列表形式返回全部能匹配的子串 re.findall(pattern, string[, flags]) finditer 搜索string,返回一个顺序访问 ... 
- C++笔记(2)——一些语法基础知识以及基本算法知识
			今天和PAT无直接相关的关系,主要是关于一些语法/算法的笔记,因为我发现自己的基础还没有打扎实,有些时候看别人的代码还会觉得一头雾水,不明白代码的含义. 一些C/C++语法 先从语法开始吧.这部分很琐 ... 
- 如何实现动态水球图  --》  echars结合echarts-liquidfill实现
			1)项目中作为项目依赖,安装到项目当中(注意必须要结合echars) npm install echarts vue-echarts --save npm install echarts-liquid ... 
- Node.js实战13:fs模块奥义!开发一个数据库。
			本文,将使用fs开发一种简单的文件型数据库. 数据库中,记录将采用JSON模式,内容型如: {"key":"a","value":" ... 
- “希希敬敬对”团队——敏捷冲刺Alpha过程总结
			“希希敬敬对”团队在七天冲刺过程中每一个小组成员都尽力去完成自己的任务.在合作过程中,总算是有一些成果出现,代码功能能够实现. 对此次冲刺有如下优缺点: 优点: 团队人员合作较多,成员都能够积极响应参 ... 
- 前端表格选中列合计,select-chosen,set集合,display隐藏
			业务涉及到table选中列合计,同时隐藏未选中列.为了减少后端请求数据,前端获得所有数据后筛选计算. 1.select下拉框初始化 $(function() { $('.chosen-select') ... 
- jenkins 启动报错
			daemon: fatal: refusing to execute unsafe program: /usr/java/jdk1.8.0/bin/java (/usr/java/jdk1.8.0/b ... 
- JAVA总结--设计模式
			三大类设计模式: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元模式. 行为 ... 
- Linux 修改hostname几种方式
			1: hostname DB-Server --运行后立即生效(新会话生效),但是在系统重启后会丢失所做的修改 2: echo DB-Server > /proc/sys ... 
- 12、前端知识点--MVVM模式
			1.MVVM与MVC的区别是什么? 在MVC里,View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑. MVC模型关注的是Model的不变,所以,在 ... 
