poj3376 Finding Palindromes【exKMP】【Trie】
| Time Limit: 10000MS | Memory Limit: 262144K | |
| Total Submissions:4710 | Accepted: 879 | |
| 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
aa aba aba abba baab
Source
#include<iostream>
//#include<bits/stdc++.h>
#include<cstdio>
#include<cmath>
//#include<cstdlib>
#include<cstring>
#include<algorithm>
//#include<queue>
#include<vector>
//#include<set>
//#include<climits>
//#include<map>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
#define N 100010
#define pi 3.1415926535
#define inf 0x3f3f3f3f const int maxn = 2e6 + ;
int n, sum_len;
char s[maxn], s_rev[maxn];
int st[maxn], ed[maxn]; int nxt[maxn], ex[maxn];
bool flag[][maxn];
void GETNEXT(char *str, int l, int r)
{
int i=l,j,po;
nxt[i]=r - l + ;//初始化next[0]
while(str[i]==str[i+]&&i<=r)//计算next[1]
i++;
nxt[l + ]=i - l;
po= + l;//初始化po的位置
for(i=+l;i<=r;i++)
{
if(nxt[i-po + l]+i - l<nxt[po]+po - l)//第一种情况,可以直接得到next[i]的值
nxt[i]=nxt[i-po + l];
else//第二种情况,要继续匹配才能得到next[i]的值
{
j=nxt[po]+po-i;
if(j<)j=;//如果i>po+next[po],则要从头开始匹配
while(i+j<=r&&str[l+j]==str[j+i])//计算next[i]
j++;
nxt[i]=j;
po=i;//更新po的位置
}
}
}
//计算extend数组
void EXKMP(char *s1,char *s2, int l, int r, int sign)
{
int i=l,j,po;
GETNEXT(s2, l, r);//计算子串的next数组
//for(j = l; j <= r; j++)cout<<nxt[j]<<endl;
while(s1[i]==s2[i]&&i<=r)//计算ex[0]
i++;
ex[l]=i - l;
po=l;//初始化po的位置
for(i=l + ;i<=r;i++)
{
if(nxt[i-po + l]+i - l<ex[po]+po -l)//第一种情况,直接可以得到ex[i]的值
ex[i]=nxt[i-po+l];
else//第二种情况,要继续匹配才能得到ex[i]的值
{
j=ex[po]+po-i;
if(j<)j=;//如果i>ex[po]+po则要从头开始匹配
while(i+j<=r&&s1[j+i]==s2[l+j])//计算ex[i]
j++;
ex[i]=j;
po=i;//更新po的位置
}
}
for(int i = l; i <= r; i++){
//cout<<ex[i]<<endl;
if(ex[i] == r - i + ){
flag[sign][i] = true;
}
}
} struct Trie{
int trie[maxn][];
int cnt[maxn];
int val[maxn];
int tot;
}tr; void init()
{
memset(flag, , sizeof(flag));
memset(nxt, , sizeof(nxt));
memset(ex, , sizeof(ex));
for(int i = ; i <= tr.tot; i++){
memset(tr.trie[i], , sizeof(tr.trie[i]));
tr.cnt[i] = ;
tr.val[i] = ;
}
tr.tot = ;
} void insertt(char *str, int l, int r)
{
int p = ;
for(int k = l; k <= r; k++){
int ch = str[k] - 'a';
tr.val[p] += flag[][k];
if(tr.trie[p][ch] == ){
tr.trie[p][ch] = ++tr.tot;
}
p = tr.trie[p][ch]; }
tr.cnt[p]++;
} LL searchh(char *str, int l, int r)
{
LL ans = ;
int p = ;
for(int k = l; k <= r; k++){
//cout<<flag[k]<<endl;
int ch = str[k] - 'a';
p = tr.trie[p][ch];
if(p == )break;
if(k < r && flag[][k + ] || k == r)ans += tr.cnt[p];
}
if(p)ans += tr.val[p];
//ans += tr.cnt[p];
return ans;
} int main()
{
while(scanf("%d", &n) != EOF){
sum_len = ;
init();
for(int i = ; i < n; i++){
int l;
scanf("%d %s", &l, s + sum_len);
for(int j = ; j < l; j++){
s_rev[sum_len + j] = s[sum_len + l - - j];
}
st[i] = sum_len;
sum_len += l;
ed[i] = sum_len - ; EXKMP(s, s_rev, st[i], ed[i], );
EXKMP(s_rev, s, st[i], ed[i], );
insertt(s, st[i], ed[i]);
} LL ans = ;
/*for(int i = 0; i < sum_len; i++){
cout<<s[i]<<" "<<flag[0][i]<<" "<<flag[1][i]<<endl;
}*/
//cout<<s<<endl;
for(int i = ; i < n; i++){
ans += searchh(s_rev, st[i], ed[i]);
}
printf("%lld\n", ans);
}
return ;
}
poj3376 Finding Palindromes【exKMP】【Trie】的更多相关文章
- POJ3376 Finding Palindromes —— 扩展KMP + Trie树
题目链接:https://vjudge.net/problem/POJ-3376 Finding Palindromes Time Limit: 10000MS Memory Limit: 262 ...
- 【BZOJ2741】【FOTILE模拟赛】L 分块+可持久化Trie树
[BZOJ2741][FOTILE模拟赛]L Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max( ...
- 【hiho一下 第四周】Trie图
[题目链接]:http://hihocoder.com/problemset/problem/1036?sid=1092555 [题意] [题解] AC自动机的模板题; 在求有没有子串的时候; 注意要 ...
- 【hiho一下第二周 】Trie树
[题目链接]:http://hihocoder.com/problemset/problem/1014 [题意] [题解] 在字典树的域里面加一个信息cnt; 表示这个节点下面,记录有多少个单词; 在 ...
- 【spring源码分析】IOC容器初始化(二)
前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...
- 「洛谷5283」「LOJ3048」「十二省联考2019」异或粽子【可持久化01trie+优先队列】
题目链接 [洛谷传送门] [LOJ传送门] 题目大意 让你求区间异或和前\(k\)大的异或和的和. 正解 这道题目是Blue sky大佬教我做的(祝贺bluesky大佬进HA省A队) 我们做过某一些题 ...
- 【codeforces】【比赛题解】#855 Codefest 17
神秘比赛,以<哈利波特>为主题……有点难. C题我熬夜切终于是写出来了,可惜比赛结束了,气啊. 比赛链接:点我. [A]汤姆·里德尔的日记 题意: 哈利波特正在摧毁神秘人的分灵体(魂器). ...
- 【BZOJ】【2434】【NOI2011】阿狸的打字机
AC自动机+DFS序+BIT 好题啊……orz PoPoQQQ 大爷 一道相似的题目:[BZOJ][3172][TJOI2013]单词 那道题也是在fail树上数有多少个点,只不过这题是在x的fail ...
- 【洛谷5439】【XR-2】永恒(树链剖分,线段树)
[洛谷5439][XR-2]永恒(树链剖分,线段树) 题面 洛谷 题解 首先两个点的\(LCP\)就是\(Trie\)树上的\(LCA\)的深度. 考虑一对点的贡献,如果这两个点不具有祖先关系,那么这 ...
随机推荐
- node服务器中打开html文件的两种方法
方法1:利用 Express 托管静态文件,详情查看这里 方法2:使用fs模块提供的readFile方法打开文件,让其以text/html的形式输出. 代码: var express = requir ...
- 如何测试hello world
最近在跟敏捷专家聊到了单元测试的相关内容. 我的问题主要集中在如何推广单元测试. 我们发现在很多团队,开发人员并不是十分愿意去写单元测试,我认为主要的原因是学习写单元测试是有成本的,很多开发同学并不愿 ...
- QT和MFC的差别
QT和MFC的差别 在使用MFC之前就已经使用Qt这个事实可能影响了我的客观性. (MFC效率较高,但大量的Windows API和消息机制使得其较难理解,不易用:QT封装较好,易用且跨平台,但效率较 ...
- [svc]find+xargs/sed&sed后向引用+awk多匹配符+过滤行绝招总结&&产生随机数
30天内的文件打包 find ./test_log -type f -mtime -30|xargs tar -cvf test_log.tar.gz find,文件+超过7天+超过1M的+按日期为文 ...
- List 比较大小
List<Player> lst = new List<Player>(); lst.Add()); lst.Add()); lst.Add()); lst.Add()); l ...
- 解决CentOS缺少共享库
# ./aapt dump bading ./tmp/app_xxxx.apk ./appt:error while loading shared libraries: libraries: libs ...
- linux每日命令(39):lsof命令
lsof(list open files)是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件.所以如传输控制协议 ...
- Spring Boot 应用 发布到Docker
Spring Boot 应用 先把命令行切换到Maven项目的根目录 E:\gitCode\galaxyguardians 通过mvn clean package命令打包应用程序 ,在E:\gitCo ...
- [转]Ubuntu 16.04安装有道词典
原文:https://www.cnblogs.com/scplee/archive/2016/05/13/5489024.html 以前用Ubuntu 14.04 的时候,直接下载有道词典官方deb安 ...
- 【iCore1S 双核心板_FPGA】例程六:状态机实验——状态机使用
核心代码: module FSM( input CLK_12M, input FPGA_KEY, output FPGA_LEDR, output FPGA_LEDG, output FPGA_LED ...