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,求分 ...
随机推荐
- Android之断点续传下载(转)
Android之断点续传下载http://www.cnblogs.com/zxl-jay/archive/2011/10/09/2204195.html
- win10不能被远程解决方案(开启远程桌面,防火墙仍不能被远程解决方案)
开启远程桌面,防火墙仍不能被远程解决方案 1.“Win+R”→“gpedit.msc” 2.依次展开“计算机配置”→“管理模版”→“系统”→“凭据分配”→找到“允许分配保存的凭据用于仅NTLM服务器身 ...
- python抓取
我要抓取奥巴马每周的演讲内容http://www.putclub.com/html/radio/VOA/presidentspeech/index.html 如果手动提取,就需要一个个点进去,再复制保 ...
- NFS服务端+客户端配置
一.Server端配置 1.下载rpcbind和nfs #yum install -y rpcbind nfs-utils 2.创建共享文件并授权 创建共享文件夹 #mkdir /server-nfs ...
- Discuz!论坛基本搭建
Crossday Discuz! Board(简称 Discuz!)是北京康盛新创科技有限责任公司推出的一套通用的社区论坛软件系统 一.LAMP环境搭建 参考地址:http://www.cnblogs ...
- PHP判断变量类型和类型转换的三种方式
前言: PHP 在变量定义中不需要(不支持)明确的类型定义.变量类型是根据使用该变量的上下文所决定的.所以,在面对页码跳转.数值计算等严格的格式需求时,就要对变量进行类型转换. 举例如下: $foo ...
- python中高阶函数与装饰器(2)
函数返回值为内置函数名: def sum(*args): def sum_in(): ax = 0 for n in args: ax = ax ...
- python实现域账号登陆
需求:公司的网路比较变态,每天到了24点自动断开,为了避免一台测试机断网,用python做了一个自动登录 原理:时间到了24点的时候,每隔10秒检测是否可以ping通www.baidu.com,如果p ...
- 递归和静态static
function sum($n){ if($==1){ return 1; } return $n+sum($n-1); } echo sum(100); ---------------------- ...
- openGL笔记-画基本图形
#include "iostream" #include <GL/glut.h> #include<cmath> #include<vector> ...