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,求分 ...
随机推荐
- process.nextTick,Promise.then,setTimeout,setImmediate执行顺序
1. 同步代码执行顺序优先级高于异步代码执行顺序优先级: 2. new Promise(fn)中的fn是同步执行: 3. process.nextTick()>Promise.then()> ...
- PDF文档小技巧整理一览
1.福昕阅读器文档背景修改为保护眼睛的颜色? 1)文件 -> 偏好设置 -> 访问 -> 勾选 "改变文档颜色" 2)选择 '自定义颜色'->'页面背景颜色 ...
- qsort和sort
sort()函数是C++中的排序函数其头文件为:#include<algorithm>头文件: qsort()是C中的排序函数,其头文件为:#include<stdlib.h> ...
- Java入门:构造方法
什么是构造方法 类体中有两大形式的成员,其中一个是成员方法(另一个就是成员变量啦~).成员方法又分两种,一种是普通成员方法,另一种是构造方法(有的资料中也称之为构造函数). 所谓构造方法,就是这个类在 ...
- linux命令总结之route命令
route命令用于显示和操作IP路由表.要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器,或者同时位于两个网络的网关来实现.在Linux系统中,设置路由通常是 为了解决以下问题:该Linu ...
- windows配置Python多版本共存
windows配置Python多版本共存 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 最近Python开发蛮火的,三年前我的一个运维朋友就告诉我说Python语言将来会很火,当时 ...
- NCPC2016-E- Exponial
题目描述 Illustration of exponial(3) (not to scale), Picture by C.M. de Talleyrand-Périgord via Wikimedi ...
- 51nod 1103 N的倍数 (鸽巢原理)
1103 N的倍数 题目来源: Ural 1302 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注 一个长度为N的数组A,从A中选出若干个数,使得这 ...
- .NET 定时器类及使用方法
Timer类实现定时任务 //2秒后开启该线程,然后每隔4s调用一次 System.Threading.Timer timer = new System.Threading.Timer((n) =&g ...
- TC-572-D1L2 未完!待续!
题目描述 • 有一个神秘的常数 K ,s 位• 现在有 n 个 s 位数,告诉你每个数与 K 有多少位是相同的• 判断 K 的无解.多解.唯一解,并求出唯一解(如果存在的话)• 所有出现的数都允许前导 ...