POJ 3376 Finding Palindromes EX-KMP+字典树
题意:
给你n个串串,每个串串可以选择和n个字符串拼接(可以自己和自己拼接),问有多少个拼接后的字符串是回文。
所有的串串长度不超过2e6;
题解:
这题由于是在POJ上,所以string也用不了,会tle。
串串个数也比较多,开不下二维的char数组,卡内存。
所以数据的预处理需要处理成一个串串,把所有的串串放在一个串里面。
记录每一个串串的起始位置和长度。
数据预处理部分就解决了。
然后就是核心思想部分了。
首先你要知道如何用EX_KMP求串串前缀和后缀是否是回文。(其实也可以用马拉车)
其实这个就是t串等于s串的反串,然后做一个EX_KMP就可以了。
不会的可以做做这一题 Best Reward HDU - 3613
于是我们处理出了所有串串的前缀和后缀是否是一个回文。
下面看这个例子 dedabc 和 cba 这个显然就是可以拼接成回文的。
由此很容易想到用字典树写这一题。
然后有3种情况
1、s的长度 > t的长度,t的反串是s的前缀,s剩下的部分是回文串。
2、s的长度 < t的长度,s的反串是t的前缀,t剩下的部分是回文串。
3、s的长度 = t的长度,t的反串等于s。
然后就是具体做法,正串放入字典树内,如果某个位置的的下一个位置pos是一个回文(这个根据上面的EX_KMP处理出来)val[pos]++;
插入完后就在最后一个节点的位置pos,ed[pos]++;
最后一步计算答案;
字典树里面存的是正串,所以查询使用反串去进行匹配,
第1种情况,假设当前节点为u,对于当前节点i,当i<len-1且从第i+1个字母往后是一个回文串的时候,ans+=ed[u]。
第2种情况,如果我们顺利的查找到s反串的尾节点u,则ans+=val[u]。
第3种情况,假设当前节点为u,对于当前节点i,当i==len-1的时候,ans+=ed[u]。
最近正在学习串串,这是我遇到的第一道需要思考的题目,感觉还是可以的。
博客鸽了这么久,是时候开始写了。
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#include <set>
#include <iostream>
#include <map>
#include <stack>
#include <string>
#include <time.h>
#include <vector>
#define pi acos(-1.0)
#define eps 1e-9
#define fi first
#define se second
#define rtl rt<<1
#define rtr rt<<1|1
#define bug printf("******\n")
#define mem(a,b) memset(a,b,sizeof(a))
#define name2str(x) #x
#define fuck(x) cout<<#x" = "<<x<<endl
#define f(a) a*a
#define sf(n) scanf("%d", &n)
#define sff(a,b) scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define sffff(a,b,c,d) scanf("%d %d %d %d", &a, &b, &c, &d)
#define pf printf
#define FRE(i,a,b) for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b) for(i = a; i < b; i++)+
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define FIN freopen("data.txt","r",stdin)
#define gcd(a,b) __gcd(a,b)
#define lowbit(x) x&-x
#define rep(i,a,b) for(int i=a;i<b;++i)
#define per(i,a,b) for(int i=a-1;i>=b;--i)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int maxn = 2e6 + ;
const int maxm = 8e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = ;
int nxt[maxn], extend[maxn], len[maxn], vis[][maxn];
char s[maxn], t[maxn];
void pre_EKMP ( char x[], int m, int nxt[] ) {
nxt[] = m;
int j = ;
while ( j + < m && x[j] == x[j + ] ) j++;
nxt[] = j;
int k = ;
for ( int i = ; i < m; i++ ) {
int p = nxt[k] + k - ;
int L = nxt[i - k];
if ( i + L < p + ) nxt[i] = L;
else {
j = max ( , p - i + );
while ( i + j < m && x[i + j] == x[j] ) j++;
nxt[i] = j;
k = i;
}
}
}
void EKMP ( char x[], int m, char y[], int n, int nxt[], int extend[], int _L, int flag ) {
pre_EKMP ( x, m, nxt );
int j = ;
while ( j < n && j < m && x[j] == y[j] ) j++;
extend[] = j;
int k = ;
for ( int i = ; i < n; i++ ) {
int p = extend[k] + k - ;
int L = nxt[i - k];
if ( i + L < p + ) extend[i] = L;
else {
j = max ( , p - i + );
while ( i + j < n && j < m && y[i + j] == x[j] ) j++;
extend[i] = j;
k = i;
}
}
for ( int i = ; i < n ; i++ )
vis[flag][_L + i] = ( i + extend[i] == n );
} struct Trie {
int ch[maxn][], val[maxn], ed[maxn];
int sz;
void init() {
memset ( ch[], , sizeof ( ch[] ) );
sz = , val[] = , ed[] = ;
}
void add ( char *s, int n, int L ) {
int u = ;
for ( int i = ; i < n; i++ ) {
int id = s[i] - 'a';
val[u] += vis[][L + i];
if ( !ch[u][id] ) {
ch[u][id] = ++sz;
memset ( ch[sz], , sizeof ( ch[sz] ) );
val[sz] = ;
ed[sz] = ;
}
u = ch[u][id];
}
ed[u]++;
}
int find ( char *s, int n, int L ) {
int u = , ret = ;
for ( int i = ; i < n; i++ ) {
int id = s[i] - 'a';
u = ch[u][id];
if ( !u ) break;
if ( ( i < n - && vis[][L + i + ] ) || i == n - )
ret += ed[u];
}
if ( u ) ret += val[u];
return ret;
}
} trie;
int n;
int main() {
while ( ~sf ( n ) ) {
mem ( vis, );
trie.init();
int tot = ;
for ( int i = ; i < n ; i++ ) {
scanf ( "%d%s", &len[i], s + tot );
memcpy ( t + tot, s + tot, len[i] );
reverse ( t + tot, t + tot + len[i] );
EKMP ( t + tot, len[i], s + tot, len[i], nxt, extend, tot, );
EKMP ( s + tot, len[i], t + tot, len[i], nxt, extend, tot, );
trie.add ( s + tot, len[i], tot );
tot += len[i];
}
LL ans = ;
tot = ;
for ( int i = ; i < n ; i++ ) {
ans += trie.find ( t + tot, len[i], tot );
tot += len[i];
}
printf ( "%lld\n", ans );
}
return ;
}
POJ 3376 Finding Palindromes EX-KMP+字典树的更多相关文章
- POJ - 3376 Finding Palindromes(拓展kmp+trie)
传送门:POJ - 3376 题意:给你n个字符串,两两结合,问有多少个是回文的: 题解:这个题真的恶心,我直接经历了5种错误类型 : ) ... 因为卡内存,所以又把字典树改成了指针版本的. 字符串 ...
- poj 3376 Finding Palindromes
Finding Palindromes http://poj.org/problem?id=3376 Time Limit: 10000MS Memory Limit: 262144K ...
- POJ3376 Finding Palindromes —— 扩展KMP + Trie树
题目链接:https://vjudge.net/problem/POJ-3376 Finding Palindromes Time Limit: 10000MS Memory Limit: 262 ...
- POJ 3376 Finding Palindromes (tire树+扩展kmp)
很不错的一个题(注意string会超时) 题意:给你n串字符串,问你两两匹配形成n*n串字符串中有多少个回文串 题解:我们首先需要想到多串字符串存储需要trie树(关键),然后我们正序插入倒序匹配就可 ...
- POJ - 3376 Finding Palindromes manacher+字典树
题意 给n个字符串,两两拼接,问拼接后的\(n\times n\)个字符串中有多少个回文串. 分析 将所有正串插入字典树中,马拉车跑出所有串哪些前缀和后缀为回文串,记录位置,用反串去字典树中查询,两字 ...
- 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(manacher求前后缀回文串+trie)
题目链接:http://poj.org/problem?id=3376 题目大意:给你n个字符串,这n个字符串可以两两组合形成n*n个字符串,求这些字符串中有几个是回文串. 解题思路:思路参考了这里: ...
- POJ 3764 - The xor-longest Path - [DFS+字典树变形]
题目链接:http://poj.org/problem?id=3764 Time Limit: 2000MS Memory Limit: 65536K Description In an edge-w ...
- poj3376 KMP+字典树求回文串数量(n*n)
Finding Palindromes Time Limit: 10000MS Memory Limit: 262144K Total Submissions: 4043 Accepted: ...
随机推荐
- HDU6315 Naive Operations 线段树
目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog Problem:Portal传送门 原题目描述在最下面. Solution ...
- [Python]PDF合成小程序PDF合成小程序
运行平台:Python3.5 用刀了PyPDF2这个库,需要提前下载好. 源码如下: import PyPDF2, os #建立一个装pdf文件的数组pdfFiles = [] for fileNam ...
- LeetCode 596. Classes More Than 5 Students (超过5名学生的课)
题目标签: 题目给了我们 courses 表格,让我们找到 一个有至少5名学生的班级. 利用group by 把班级分类,在用Having count 来判断是否有5名,注意这里还需要用 distin ...
- 将数据写到kafka的topic
package test05 import java.util.Propertiesimport org.apache.kafka.clients.producer.{KafkaProducer, P ...
- Pod 私有仓库构建
Pod 私有仓库构建 创建`私有仓库索引库`(iOS) 添加`私有仓库索引库`到本地repo管理 创建自己的`组建库工程 上传`组建库工程`到`私有仓库索引库` App工程调用`组建库工程` 目的 私 ...
- iOS开发系列-iOS适配
概述 发布iPhone X 系统版本为iOS11, 由于刘海屏原因需要对新的机型做适配. iPhone X safeArea iOS11苹果提出safeArea替代iOS7引入 topLayoutGu ...
- Shell 学习(二)
目录 Shell 学习(二) 1 设置环境变量 1.1 基本语法 1.2 实践 2 位置参数变量 2.1 介绍 2.2 基本语法 2.3 位置参数变量应用实例 3 预定义变量 3.1 基本介绍 3.2 ...
- JS对象 向下取整floor() floor() 方法可对一个数进行向下取整。 语法: Math.floor(x)
向下取整floor() floor() 方法可对一个数进行向下取整. 语法: Math.floor(x) 参数说明: 注意:返回的是小于或等于x,并且与 x 最接近的整数. 我们将在不同的数字上使用 ...
- JavaScript - DOM相关
DOM节点分类 ( node ) : 元素节点 ( element node ) 属性节点 ( attribute node ) 文本节点 ( text node) DOM的相关操作 : 1. 查询元 ...
- JavaScript 数据值校验工具类
/** * 数据值校验工具类 */ var checkService = { // 不校验 none: function () { return true; }, //非空校验 isEmpty: fu ...