POJ 3376 Finding Palindromes(manacher求前后缀回文串+trie)
题目链接: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)的更多相关文章
- HDU 3613 Best Reward(扩展KMP求前后缀回文串)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3613 题目大意: 大意就是将字符串s分成两部分子串,若子串是回文串则需计算价值,否则价值为0,求分割 ...
- POJ - 3376 Finding Palindromes manacher+字典树
题意 给n个字符串,两两拼接,问拼接后的\(n\times n\)个字符串中有多少个回文串. 分析 将所有正串插入字典树中,马拉车跑出所有串哪些前缀和后缀为回文串,记录位置,用反串去字典树中查询,两字 ...
- POJ 3376 Finding Palindromes (tire树+扩展kmp)
很不错的一个题(注意string会超时) 题意:给你n串字符串,问你两两匹配形成n*n串字符串中有多少个回文串 题解:我们首先需要想到多串字符串存储需要trie树(关键),然后我们正序插入倒序匹配就可 ...
- Manacher算法 - 求最长回文串的利器
求最长回文串的利器 - Manacher算法 Manacher主要是用来求某个字符串的最长回文子串. 不要被manacher这个名字吓倒了,其实manacher算法很简单,也很容易理解,程序短,时间复 ...
- Manacher(最长镜面回文串)
I - O'My! Gym - 101350I Note: this is a harder version of Mirrored string I. The gorillas have recen ...
- poj 3376 Finding Palindromes
Finding Palindromes http://poj.org/problem?id=3376 Time Limit: 10000MS Memory Limit: 262144K ...
- POJ 3376 Finding Palindromes(扩展kmp+trie)
题目链接:http://poj.org/problem?id=3376 题意:给你n个字符串m1.m2.m3...mn 求S = mimj(1=<i,j<=n)是回文串的数量 思路:我们考 ...
- POJ - 3376 Finding Palindromes(拓展kmp+trie)
传送门:POJ - 3376 题意:给你n个字符串,两两结合,问有多少个是回文的: 题解:这个题真的恶心,我直接经历了5种错误类型 : ) ... 因为卡内存,所以又把字典树改成了指针版本的. 字符串 ...
- HDU 3613 Best Reward(manacher求前、后缀回文串)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3613 题目大意: 题目大意就是将字符串s分成两部分子串,若子串是回文串则需计算价值,否则价值为0,求分 ...
随机推荐
- BZOJ 2140 稳定婚姻
2140: 稳定婚姻 Description 我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚姻问题的专家认为,是与简化离婚手续有关. 25岁的 ...
- js字符串替换(时间转换)
转: js中字符串全部替换 废话不多说,直接发结果 在js中字符串全部替换可以用以下方法: str.replace(/需要替换的字符串/g,"新字符串") 比如: "yy ...
- python学习(20) 网络编程
原文链接:http://www.limerence2017.com/2018/01/02/python20/ python 网络编程和基本的C语言编程一样,效率不是很高,如果为了封装通信库建议采用C/ ...
- 我的编码习惯 - Controller规范
原文出处: 晓风轻 请先阅读我这2篇文章 程序员你为什么这么累? 和 我的编码习惯 - 接口定义. 第一篇文章中,我贴了2段代码,第一个是原生态的,第2段是我指定了接口定义规范,使用AOP技术之后最终 ...
- 我的Pycharm,我做主
之间花了一周多的时间把Pycharm官方帮助文档翻译了一遍,一共43篇博客,累得要屎,感悟颇多. 发牢骚之前先总结点干货,这里把所有的翻译文档列成如下目录,方便大家索引: 最全Pycharm教程(1) ...
- LeetCode-330.Patching Array
/** * nums的所有元素,假设最大能连续形成[1,sum] 当增加一个element的时候 * 会变成 [1,sum] [element+1,sum+element]两个区间,这两个区间有以下可 ...
- windows查找端口占用/ 终结端口占用 ------------windows小技巧
前沿 我是一名小程序员,经常通过一些类似tomcat,jettry 等服务器工具 调试项目.有时候莫名其妙的就会出现 程序关闭不正常的情况!去查端口又死活找不到!最后只能重启电脑 后面,在网上查了一些 ...
- ASP.NET CORE API Swagger+IdentityServer4授权验证
简介 本来不想写这篇博文,但在网上找到的文章博客都没有完整配置信息,所以这里记录下. 不了解IdentityServer4的可以看看我之前写的入门博文 Swagger 官方演示地址 源码地址 配置Id ...
- CF&&CC百套计划2 CodeChef December Challenge 2017 Penalty Shoot-out
https://www.codechef.com/DEC17/problems/CPLAY #include<cstdio> #include<algorithm> using ...
- JavaScript 生成n位随机数
function RndNum(n){ var rnd=""; for(var i=0;i<n;i++) rnd+=Math.floor(Math.random()*10); ...