题目链接:http://poj.org/problem?id=3376

题目大意:给你n个字符串,这n个字符串可以两两组合形成n*n个字符串,求这些字符串中有几个是回文串。

解题思路:思路参考了这里:http://blog.csdn.net/qq_30241305/article/details/50718051

做法:首先由两个字符串A,B.要使它们能组成回文串有三种情况

情况① :alen < blen

    abc  abacba  abcaba   

     A               B    RB

如上所示,A是B的反串前缀,且b的剩余部分可以认为是后缀是回文串

情况②:alen > blen

  abcaba  cba  abc

   A    B   RB

B的反串是A的前缀,且a的后缀是回文串

情况③:alen == blen

b是a的反串,这个就不用解释了吧。

现将所有正序字符(原字符串)串建立在字典树中。然后用反串去匹配,根据上面给出的三种情况作出判断。

另外:因为只给了字符串的总长度,所以,只开一维的字符串数组,每次接着上次字符串结束的位置开始即可。为了方便,记录字符串开始的位置,和结束的位置。

代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=2e6+; LL ans;
int n,len1,len2,idx,root;
char s[N],str[N*];
int trie[N][],p[N*],End[N],hou[N];//End[i]表示以节点i为结尾的字符串的数目
//hou[i]表示节点i之后(不包括i)的后缀回文串数目 struct node{
int st,len;
}a[N]; void init(){
str[]='$';
str[]='#';
len1--;
for(int i=;i<=len1;i++){
str[i*]=s[i];
str[i*+]='#';
}
len2=len1*+;
str[len2]='@';
} void manacher(){
init();
int id=-,mx=-;
for(int i=;i<len2;i++){
if(mx>i) p[i]=min(p[id*-i],mx-i);
else p[i]=;
while(str[i-p[i]]==str[i+p[i]])
p[i]++;
if(i+p[i]>mx){
mx=i+p[i];
id=i;
}
}
} //将字符串正序插入字典树中
void Insert(){
for(int i=;i<n;i++){
int now=root;
for(int j=a[i].st;j<a[i].st+a[i].len;j++){
if(!trie[now][s[j]-'a']) trie[now][s[j]-'a']=++idx;
now=trie[now][s[j]-'a'];
int mid=((j+)*-+(a[i].st+a[i].len-)*+)/;//(j+1)*2是s[j+1]对应str的位置(j+1)*2-1则是边缘的'#',同理(a[i].st+a[i].len-1)*2+1也对应边缘'#'
if(p[mid]>mid-(j+)*+)
hou[now]++;
}
hou[now]--; //因为字符串末尾的"#"也算成一个回文串了,所以要减掉
End[now]++;
}
} //计算可以生成的回文串数
void Find(){
for(int i=;i<n;i++){
int now=root;
for(int j=a[i].st+a[i].len-;j>=a[i].st;j--){
//匹配失败,没有对应的字符串
if(!trie[now][s[j]-'a']){
now=-;
break;
}
now=trie[now][s[j]-'a'];
if(End[now]){ //情况①或③
int mid=(a[i].st*-+(j-)*+)/;
if(p[mid]>mid-a[i].st*+)
ans+=End[now];
}
}
if(now!=-) ans+=hou[now]; //情况②
}
} int main(){
while(~scanf("%d",&n)){
idx=,len1=,ans=;
memset(trie,,sizeof(trie));
memset(End,,sizeof(End));
memset(hou,,sizeof(hou));
for(int i=;i<n;i++){
scanf("%d",&a[i].len);
scanf("%s",s+len1);
a[i].st=len1;
len1+=a[i].len;
}
manacher();
Insert();
Find();
printf("%lld\n",ans);
}
return ;
}

POJ 3376 Finding Palindromes(manacher求前后缀回文串+trie)的更多相关文章

  1. HDU 3613 Best Reward(扩展KMP求前后缀回文串)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3613 题目大意: 大意就是将字符串s分成两部分子串,若子串是回文串则需计算价值,否则价值为0,求分割 ...

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

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

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

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

  4. Manacher算法 - 求最长回文串的利器

    求最长回文串的利器 - Manacher算法 Manacher主要是用来求某个字符串的最长回文子串. 不要被manacher这个名字吓倒了,其实manacher算法很简单,也很容易理解,程序短,时间复 ...

  5. Manacher(最长镜面回文串)

    I - O'My! Gym - 101350I Note: this is a harder version of Mirrored string I. The gorillas have recen ...

  6. poj 3376 Finding Palindromes

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

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

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

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

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

  9. HDU 3613 Best Reward(manacher求前、后缀回文串)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3613 题目大意: 题目大意就是将字符串s分成两部分子串,若子串是回文串则需计算价值,否则价值为0,求分 ...

随机推荐

  1. python之旅:绑定方法与非绑定方法

    一 类中定义的函数分成两大类 一:绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入): 1. 绑定到类的方法:用classmethod装饰器装饰的方法.                 为 ...

  2. zuul学习

    1.zuul可以代理界面所需的后端服务,可以解决CORS(Cross-Origion-Resource-Sharing)和认证问题(authentication)问题 2.zuul是使用ribbon来 ...

  3. HDU 6231

    K-th Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Tot ...

  4. python数据结构(1)

    四种内建的数据结构:List.Tuple.Dictionary以及Set. 1.列表 列表是可变的,这是它区别于字符串和元组的最重要的特点,一句话概括即:列表可以修改,而字符串和元组不能. (1).创 ...

  5. 页面缓存之Meta http-equiv属性详解

    http-equiv顾名思义,相当于http的文件头作用,它可以向浏览器传回一些有用的信息,以帮助正确和精确地显示网页内容,与之对应的属性值为content,content中的内容其实就是各个参数的变 ...

  6. NandFlash、NorFlash、DataFlash、SDRAM释义

    1. NandFlash和NorFlash       Flash存储芯片,俗称闪存,因其具有非易失性.可擦除性.可重复编程及高密度.低功耗等特点,广泛地应用于手机.数码相机.笔记本电脑等产品.    ...

  7. Centos7远程桌面 vnc/vnc-server的设置

    Centos7与Centos6.x有了很大的不同. 为了给一台服务器装上远程桌面,走了不少弯路.写这篇博文,纯粹为了记录,以后如果遇到相同问题,可以追溯. 1.假定你的系统没有安装vnc的任何软件,那 ...

  8. tips 前端 bootstrap 嵌套行 嵌套列 溢出 宽度不正确 栅格化系统计算

    bootstrap 当嵌套列时 有时会出现很奇异的row 的width不对问题出现的情况时 <div class="row" > <!--row a--> ...

  9. [整理]C语言中字符常量与ASCII码

    所有的ASCII码都可以用“\”加数字(一般是8进制数字)来表示.而C中定义了一些字母前加"\"来表示常见的那些不能显示的ASCII字符,如\0,\t,\n等,就称为转义字符,因为 ...

  10. 最长递增子序列(LIS)(转)

    最长递增子序列(LIS)   本博文转自作者:Yx.Ac   文章来源:勇幸|Thinking (http://www.ahathinking.com)   --- 最长递增子序列又叫做最长上升子序列 ...