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. SGU 326 Perspective(最大流)

    Description Breaking news! A Russian billionaire has bought a yet undisclosed NBA team. He's plannin ...

  2. 最全NB-IoT/eMTC物联网解决方案名录汇总

    NB-IoT/eMTC等蜂窝物联网技术的成熟和商用,占据低功耗广域网络(LPWAN)的主流地位,推动全球物联网新一轮发展热潮,越来越多的行业开始采用物联网方案来解决解决实际问题.实现落地应用,越来越多 ...

  3. 异常概念和处理机制,try-catch-finally,throw和throws,自定义异常

    异常概念和处理机制 什么是异常? 所谓异常就是指在程序运行的过程中发生的一些不正常事件.(如除0溢出,数组下标越界,所要读取的文件不存在); 异常导致的后果? Java程序的执行过程中如出现异常事件, ...

  4. Android开发随笔5

    昨天: 对界面的进一步设计补充 可以在界面之间的跳转 研究了对图标等的操作 今天: 实现对库的相关操作 学习视视频内容‘ 复习java的一些知识.

  5. [离散化]人潮最多的時段( Interval Partitioning Problem )

    範例:人潮最多的時段( Interval Partitioning Problem ) 一群訪客參加宴會,我們詢問到每一位訪客的進場時刻與出場時刻,請問宴會現場擠進最多人的時段. 換個角度想,想像會場 ...

  6. jspSmartUpload上传下载使用例子

    --------------------------------------------------------------------- ServletUpload.java 上传 package ...

  7. Java中I/O流之Print流

    Java 中的 print 流: print 流用于做输出将会非常的方便,并且具有以下特点: 1. printWriter.printStream 都属于输出流,分别针对字符,字节. 2. print ...

  8. (十一)instanceof 和 getclass 的区别

    判断两个对象是否为同一类型,时常用到getclass 和 instanceof ,而这两个函数又是时常让人混淆.下面从一个例子说明两者的区别: public class Test_drive { pu ...

  9. YaoLingJump开发者日志(七)

      LGame用起来真是各种蛋疼,插背景都可以显示不出来.在屏幕结束后释放资源,重载该屏幕时再setbackground也不行,直接用Lpaper当background更不行,会把tilemap上的东 ...

  10. vue-cli3配置postcss-cssnext

    1. // npm install autoprefixer --save-dev 此步不需要了,因为postcss-cssnext自带这个依赖 npm install postcss-cssnext ...