Finding Palindromes
Time Limit: 10000MS   Memory Limit: 262144K
     
Case Time Limit: 2000MS

Description

A word is called a palindrome if we read from right to left is as same as we read from left to right. For example, "dad", "eye" and "racecar" are all palindromes, but "odd", "see" and "orange" are not palindromes.

Given n strings, you can generate n × n pairs of them and concatenate the pairs into single words. The task is to count how many of the so generated words are palindromes.

Input

The first line of input file contains the number of strings n. The following n lines describe each string:

The i+1-th line contains the length of the i-th string li, then a single space and a string of li small letters of English alphabet.

You can assume that the total length of all strings will not exceed 2,000,000. Two strings in different line may be the same.

Output

Print out only one integer, the number of palindromes.

Sample Input

3
1 a
2 ab
2 ba

Sample Output

5

Hint

The 5 palindromes are: 
aa aba aba abba baab 
 
建立trie树
用原串的反串在trie树上匹配
假设反串匹配到i,trie树上到j
1、如果j是单词节点,即以j结尾的单词是反串的前缀,那么如果i以后(反串剩余的部分,不包括i)是回文串,以j结尾的单词都可以与匹配的单词构成回文串
2、如果反串匹配完了,即反串是以i结尾的单词的前缀,那么j后面(不包括j)有多少回文串,就可以产生多少合法答案
关键:字符串的前缀回文和后缀回文
用扩展kmp
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 2000008
using namespace std;
bool f[][N];
long long ans;
char T[N],S[N];
int len,tot,root,id;
int st[N],ed[N],cnt;
int nxt[N],expand[N];
int trie[N][],mark[N],sum[N];
void getnxt(char *s,int ll,int rr)
{
int a=ll;
nxt[]=rr-ll+;
while(a+<=rr && s[a]==s[a+]) a++;
nxt[]=a-ll;
a=+ll;
int p,l,j;
for(int k=+ll;k<=rr;k++)
{
p=a-ll+nxt[a-ll]-; l=nxt[k-a];
if(k-ll+l->=p)
{
j=p-k+ll+> ? p-k+ll+ : ;
while(k+j<=rr && s[k+j]==s[j+ll]) j++;
nxt[k-ll]=j;
a=k;
}
else nxt[k-ll]=l;
}
}
void exkmp(char *s,char *t,int ll,int rr,int w)
{
getnxt(t,ll,rr);
int a=ll;
while(a<=rr && s[a]==t[a]) a++;
expand[]=a-ll;
a=ll;
int p,l,j;
for(int k=ll+;k<=rr;k++)
{
p=a-ll+expand[a-ll]-; l=nxt[k-a];
if(k-ll+l->=p)
{
j=p-k+ll+> ? p-k+ll+ : ;
while(k+j<=rr && s[k+j]==t[j+ll]) j++;
expand[k-ll]=j;
a=k;
}
else expand[k-ll]=l;
}
for(int i=ll-ll;i<=rr-ll;i++)
if(i+expand[i]==rr-ll+) f[w][i+ll]=true;
}
void insert(int ll,int rr)
{
root=;
for(int i=ll;i<=rr;i++)
{
id=S[i]-'a';
sum[root]+=f[][i];
if(!trie[root][id]) trie[root][id]=++tot;
root=trie[root][id];
}
mark[root]++;
}
void find(int ll,int rr)
{
root=;
for(int i=ll;i<=rr;i++)
{
id=T[i]-'a';
root=trie[root][id];
if(!root) return;
if(i!=rr&&f[][i+] || i==rr) ans+=mark[root];
}
ans+=sum[root];
}
int main()
{
int n;
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d%s",&len,S+cnt);
for(int j=;j<len;j++) T[cnt+j]=S[cnt+len-j-];
st[i]=cnt;
ed[i]=cnt+len-;
exkmp(S,T,st[i],ed[i],);
exkmp(T,S,st[i],ed[i],);
cnt+=len;
insert(st[i],ed[i]);
}
for(int i=;i<=n;i++)
find(st[i],ed[i]);
printf("%lld\n",ans);
}

poj 3376 Finding Palindromes的更多相关文章

  1. POJ - 3376 Finding Palindromes(拓展kmp+trie)

    传送门:POJ - 3376 题意:给你n个字符串,两两结合,问有多少个是回文的: 题解:这个题真的恶心,我直接经历了5种错误类型 : ) ... 因为卡内存,所以又把字典树改成了指针版本的. 字符串 ...

  2. POJ 3376 Finding Palindromes(扩展kmp+trie)

    题目链接:http://poj.org/problem?id=3376 题意:给你n个字符串m1.m2.m3...mn 求S = mimj(1=<i,j<=n)是回文串的数量 思路:我们考 ...

  3. POJ 3376 Finding Palindromes(manacher求前后缀回文串+trie)

    题目链接:http://poj.org/problem?id=3376 题目大意:给你n个字符串,这n个字符串可以两两组合形成n*n个字符串,求这些字符串中有几个是回文串. 解题思路:思路参考了这里: ...

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

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

  5. POJ 3376 Finding Palindromes (tire树+扩展kmp)

    很不错的一个题(注意string会超时) 题意:给你n串字符串,问你两两匹配形成n*n串字符串中有多少个回文串 题解:我们首先需要想到多串字符串存储需要trie树(关键),然后我们正序插入倒序匹配就可 ...

  6. POJ - 3376 Finding Palindromes manacher+字典树

    题意 给n个字符串,两两拼接,问拼接后的\(n\times n\)个字符串中有多少个回文串. 分析 将所有正串插入字典树中,马拉车跑出所有串哪些前缀和后缀为回文串,记录位置,用反串去字典树中查询,两字 ...

  7. poj3376 Finding Palindromes【exKMP】【Trie】

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

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

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

  9. POJ 2049— Finding Nemo(三维BFS)10/200

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u013497151/article/details/29562915 海底总动员.... 这个题開始 ...

随机推荐

  1. 20145214 《Java程序设计》第6周学习总结

    20145214 <Java程序设计>第6周学习总结 教材学习内容总结 串流设计 Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串流对象. 输入串流代表对象为java. ...

  2. P4编程环境搭建遇到的问题与解决方法

    在经历了无数的折腾之后,算是折腾,最后采用的是陈翔学长的脚本加上可爱的shell调整装好的. 链接:p4Install 也许是ubuntu18.04的问题,也有可能是我自己把这个系统折腾的有点杂乱的原 ...

  3. ubuntu中下载sublime相关问题

    1.SublimeText3的安装 在网上搜索了一些ubuntu下关于sublime-text-3安装的方法,在这里针对自己尝试的情况进行反馈: 方法一(未成功): 在终端输入以下代码: sudo a ...

  4. 使用协程(gevent)实现请求

    协程,又称微线程.英文名Coroutine. 协程最大的优势就是协程极高的执行效率.因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就 ...

  5. HDU 2117 Just a Numble

    http://acm.hdu.edu.cn/showproblem.php?pid=2117 Problem Description Now give you two integers n m, yo ...

  6. 判断滚动条滚动到document底部

    滚动条没有实际的高度.只是为了呈现效果才在外型上面有长度. 在js当中也没有提供滚动条的高度API. 参考了网上有关资料:判断滚动条到底部的基本逻辑是滚动条滚动的高度加上视口的高度,正好是docume ...

  7. Delphi SQL语句字符串拼接

    单引号必须成对出现,最外层的单引号表示其内部符号为字符:除最外层以外的单引号,每两个单引号代表一个'字符.加号:+用于字符串之间的连接.字符串常量用四个单引号,例如 ' select * from T ...

  8. 【bzoj1010】[HNOI2008]玩具装箱toy 斜率优化dp

    题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具, ...

  9. NOIP2018初赛 游记

    这玩意写个鬼游记啊 听说普及+提高的考两张卷子€€£也是想得出来 怎么监考还能咕咕咕的啊 怎么我到快结束了才做完啊 怎么我根本不知道初赛能带啥啊 怎么dij我都能想着对的选了错的啊 怎么我根本不知道图 ...

  10. BZOJ4240 有趣的家庭菜园(贪心+树状数组)

    显然相当于使序列变成单峰.给原序列每个数按位置标号,则要求重排后的序列原标号的逆序对数最少.考虑将数从大到小放进新序列,那么贪心的考虑放在左边还是右边即可,因为更小的数一定会在其两侧,与它自身放在哪无 ...