题目链接: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. 洛谷 P4294 [WC2008]游览计划

    题目链接 不是很会呢,但似乎抄了题解后有点明白了 sol:状态DP显然,其实是要构建一棵最小生成树一样的东西,我自己的理解(可能不是很对哦希望多多指教)f[x][y][zt]就是到x,y这个点,状态为 ...

  2. Nodejs+Express+Mysql实现简单用户管理增删改查

    源码地址 https://github.com/king-y/NodeJs/tree/master/user 目录结构 mysql.js var mysql = require('mysql'); v ...

  3. AC自动机-HDU3065-简单题

    http://acm.hdu.edu.cn/showproblem.php?pid=3065 需要记录匹配情况的AC自动机,没有清空一些数组导致wa了几发. /*------------------- ...

  4. MT【228】整数解的个数

    求方程$x+y+z=24$的整数解的个数,要求$1\le x\le 5,12\le y\le 18,-1\le z\le12$ 解:设$a_r$是方程$X+Y+Z=r$的满足上述要求的整数解的个数,那 ...

  5. MT【23】用算术几何不等式证明数列极限存在

    评:如果不需要精确到3,上界的求法可以利用$$(1+\frac{1}{n})^n*\frac{1}{2}*\frac{1}{2}<(\frac{n+\frac{1}{n}*n+\frac{1}{ ...

  6. 在Java Web程序中使用监听器可以通过以下两种方法

    之前学习了很多涉及servlet的内容,本小结我们说一下监听器,说起监听器,编过桌面程序和手机App的都不陌生,常见的套路都是拖一个控件,然后给它绑定一个监听器,即可以对该对象的事件进行监听以便发生响 ...

  7. 自学Python1.4-Centos内vim中文乱码问题

    自学Python之路 自学Python1.4-Centos内vim中文乱码问题 1. 登陆的系统---区域语言设置 1.1查看安装中文包: 查看系统是否安装中文语言包 (列出所有可用的公共语言环境的名 ...

  8. oracle安装教程及常用命令

    虽然网上已经有很多安装教程了,但还是写一个记录一下自己的安装过程以及遇到问题的解决办法 1 安装包下载: 去oracle的官网:https://www.oracle.com/index.html  选 ...

  9. 牛客练习赛 小A与任务 解题报告

    小A与任务 链接: https://ac.nowcoder.com/acm/contest/369/B 来源:牛客网 题目描述 小A手头有 \(n\) 份任务,他可以以任意顺序完成这些任务,只有完成当 ...

  10. luoguU38228 签到题 (BSGS)

    签到一脸 $a_n=10a_{n-1}+1$求出通项$a_n=\frac{10^n-1}{9}$,然后可以化成$10^n=9K+1 (mod m)$,求一个最小的n 然后我们知道这个n一定是<= ...