题目链接:https://cn.vjudge.net/contest/283743#problem/B

题目大意:给你n个字符串,然后问你将这位n个字符串任意两两组合,然后问你这所有的n*n种情况中,是回文串的有多少个?

题目大意:学到了一个很骚气的存储多个零散字符串的方法,因为有可能个给你很多零散的字符串,我们可以将这些字符串存储在一个字符串里面,然后再额外加一个数组记录每一个字符串的开始位置和截止位置就好了。 然后是对于这个题,首先说一下判断字符串的方法,对于每一个字符串我们通过manacher算法求出每一个点的最长的回文串,然后在字典树中反序存储这个字符串。

举个例子:aaba和baa,这个时候baa插在aaba后面是可以构成回文串的,在字典树中baa是倒序存储的,所以就能够和aaba的前缀aab相匹配,然后我们在看aab后面的子串是不是回文串,如果是回文串的话,这个两个就能够形成回文串,因为前面部分和后面部分是对称的,并且中间部分也是回文串。

我们对于每一个字符串,

surf[i]记录的是对于当前的字符串,从第i+1个位置开始,能不能构成字符串。

pre[i]数组记录的是对于当前的字符串,从当前字符串的第一个位置开始到第i-1个位置,前缀能不能构成回文串。

val[i]数组记录的是字典树中从第0个位置到i所形成的的字符串的个数。

qian[i]数组记录的是当前节点后面是回文串的数目。

查询的时候,一共有两种情况:

一种是题目中说的aaba和bba这种情况,到了某一个字符串的位置之后,这个位置之前的有对称的字符串,这个位置之后的是一个回文串。

另一种是一个字符串是回文串,一直到底部都是能构成回文串的,这个时候还应该加上一直到这个字符串底部的回文串的个数就可以了。

每一次查询当前节点后面是不是回文串,如果是的话就加上这个字符串的个数。如果找到了底部还需要注意后面形成的回文串的个数。

AC代码:

 #include<iostream>
#include<stack>
#include<iomanip>
#include<cmath>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
# define ll long long
const int maxn = 2e6+;
const int maxm= 2e6+;
char str[maxn],tmp[maxn<<];
bool pre[maxn],suf[maxn];
int pp[maxn<<],tot;
int qian[maxn],val[maxn];
int start[maxn];
int ch[maxn][];
void init()
{
for(int i=; i<=tot; i++)
{
qian[i]=,val[i]=;
for(int j=; j<; j++)
{
ch[i][j]=;
}
}
tot=;
}
void trie(int t)
{
int p=;
for(int i=start[t+]-; i>=start[t]; i--)
{
int tmp=str[i]-'a';
qian[p]+=pre[i];
if(!ch[p][tmp])
ch[p][tmp]=++tot;
p=ch[p][tmp];
}
val[p]+=;
}
void manacher(int n)
{
int i,mx=,len=,id=;
tmp[]='$';
for(i=start[n]; i<start[n+]; i++)
{
tmp[len++]='#';
tmp[len++]=str[i];
pre[i]=;
suf[i]=;
}
tmp[len]='#';
tmp[len+]=;
for(int i=; i<len; i++)
{
pp[i] = ;
if(pp[id]+id > i)
pp[i] = min(pp[id*-i], pp[id]+id-i);
while(tmp[ i+pp[i] ] == tmp[ i-pp[i] ])
pp[i]++;
if(pp[id]+id < pp[i]+i)
id = i;
if(pp[i]==i)
pre[start[n]+pp[i]-]=;
if(i+pp[i]-==len)
suf[start[n+]-pp[i]+]=;
}
}
ll query(int t)
{
ll sum=;
int p=,i;
for( i=start[t]; i<start[t+]; i++)
{
int tmp=str[i]-'a';
if(ch[p][tmp]==)
break;
p=ch[p][tmp];
if(suf[i+]==||i+==start[t+])
sum+=val[p];
}
if(i==start[t+])
sum+=qian[p];
return sum;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
init();
int len;
for(int i=; i<=n; i++)
{
scanf("%d%s",&len,str+start[i]);
start[i+]=start[i]+len;
manacher(i);
trie(i);
}
ll ans=;
for(int i=; i<=n; i++)
{
ans+=query(i);
}
printf("%lld\n",ans);
}
return ;
}

B - Finding Palindromes (字典树+manacher)的更多相关文章

  1. POJ 3376 Finding Palindromes EX-KMP+字典树

    题意: 给你n个串串,每个串串可以选择和n个字符串拼接(可以自己和自己拼接),问有多少个拼接后的字符串是回文. 所有的串串长度不超过2e6: 题解: 这题由于是在POJ上,所以string也用不了,会 ...

  2. Finding Palindromes - 猥琐的字符串(Manacher+trie)

    题目大意:有 N 个字符串,所有的字符串长度不超过 200W 任意俩俩字符串可以自由组合,问组合的字符串是回文串的个数有多少个?   分析:这是一个相当猥琐的字符串处理,因为没有说单个的字符串最少多长 ...

  3. POJ3376 Finding Palindromes —— 扩展KMP + Trie树

    题目链接:https://vjudge.net/problem/POJ-3376 Finding Palindromes Time Limit: 10000MS   Memory Limit: 262 ...

  4. poj3376 Finding Palindromes【exKMP】【Trie】

    Finding Palindromes Time Limit: 10000MS   Memory Limit: 262144K Total Submissions:4710   Accepted: 8 ...

  5. 字典树 - A Poet Computer

    The ACM team is working on an AI project called (Eih Eye Three) that allows computers to write poems ...

  6. ACM: Gym 100935F A Poet Computer - 字典树

    Gym 100935F A Poet Computer Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d &am ...

  7. Trie树(字典树)(1)

    Trie树.又称字典树,单词查找树或者前缀树,是一种用于高速检索的多叉树结构. Trie树与二叉搜索树不同,键不是直接保存在节点中,而是由节点在树中的位置决定. 一个节点的全部子孙都有同样的前缀(pr ...

  8. poj 3376 Finding Palindromes

    Finding Palindromes http://poj.org/problem?id=3376 Time Limit: 10000MS   Memory Limit: 262144K       ...

  9. 019(The XOR Largest Pair)(字典树)

    题目:http://ybt.ssoier.cn:8088/problem_show.php?pid=1472 题目思路:异或是啥呀? 异或就是把两个数字变成位数相同的二进制在同位比较,相同为0,不同为 ...

随机推荐

  1. ELK--filebeat命令行参数解释

    ./filebeat 使用-c命令行上的标志设置要加载的配置文件,可以通过重复-c标志来指定多个配置文件, 可以使用覆盖个别设置-E <setting>=<value>.< ...

  2. BZOJ2124 等差子序列(树状数组+哈希)

    容易想到一种暴力的做法:枚举中间的位置,设该位置权值为x,如果其两边存在权值关于x对称即合法. 问题是如何快速寻找这个东西是否存在.考虑仅将该位置左边出现的权值标1.那么若在值域上若关于x对称的两权值 ...

  3. Codeforces976E Well played! 【贪心】

    题目分析: 由于乘二的收获很大,所以我们可以证明乘的数一定是同一个,接着排序后依次选取,判断一下即可. 题目代码: #include<bits/stdc++.h> using namesp ...

  4. LOJ #2540. 「PKUWC 2018」随机算法(概率dp)

    题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...

  5. java freemarker导出word时添加或勾选复选框

    最近项目导出word碰到一个需求,要求根据数据动态的决定word里的复选框是否勾选, 公司导出word用的是freemarker,相比较其他技术,freemarker可以很容易的控制输出样式, 在wo ...

  6. 【转】Context Switches上下文切换性能详解

    http://blog.csdn.net/aiai5251/article/details/50015745 Context Switches 上下文切换,有时也被称为进程切换(process swi ...

  7. re正则模块(二十五)

    一:什么是正则? 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则.(在Python中)它内嵌在Python中,并通过 r ...

  8. powerdesigner 字段添加注释和默认值

    powerdesigner 字段添加注释和默认值 2017年01月06日 10:59:02 qingzhuoran 阅读数:27161更多 个人分类: powerdesigner   1.选中表,右键 ...

  9. SIFT算法详解

    尺度不变特征变换匹配算法详解Scale Invariant Feature Transform(SIFT)Just For Fun zdd  zddmail@gmail.com or (zddhub@ ...

  10. Windows7 64下搭建Caffe+python接口环境

    参考链接: http://www.cnblogs.com/yixuan-xu/p/5858595.html http://www.cnblogs.com/zf-blog/p/6139044.html ...