POJ - 3376 Finding Palindromes(拓展kmp+trie)
传送门:POJ - 3376
题意:给你n个字符串,两两结合,问有多少个是回文的;
题解:这个题真的恶心,我直接经历了5种错误类型 : ) ... 因为卡内存,所以又把字典树改成了指针版本的。
字符串s与字符串t组合是回文串的情况
1. len(s) > len(t), t的反串是 s 的前缀,且s剩下的部分是回文串 (比如s: abbcb t: ba
2. len(s) = len(t), s = t 的反串(比如s: abc t: cba
3. len(s) < len(t), s 是 t 的反串的前缀,且 t 的反串剩下的部分是回文串(比如 s: ba t: bbcb
用拓展kmp求出每个字符串的最长回文前缀和后缀(分别用原串和反串进行exkmp,用反串和原串进行exkmp就可以求出了)然后用原串建trie,用反串去匹配。
1. 在trie中, 若串在非结点位置匹配完成, 则把该节点往下走有多少个回文串累加到答案。
2. 在trie中, 若在匹配串时遇上在这个结点结束的字符串, 那么看剩下的后缀是否是回文, 若是, 则把在该点结束的字符串数目累加到答案。
将所有的字符串都放在一个数组里,用一个数组记录每个串的起点,这样能节省空间。
如果内存超了不妨看看这个地方 int tree[26]; 是不是开了30,26就过了.....
1 #include<iostream>
2 #include<algorithm>
3 #include<string.h>
4 #define ll long long
5 using namespace std;
6
7 ///next[i]: T[i]到T[m - 1]与T(模式串)的最长相同前缀长度;
8 ///extend[i]: S[i]到S[n - 1](原串)与T的最长相同前缀长度。
9
10 const int maxn=2000100;
11 int nt[maxn],ex[maxn],k=1,be[maxn],len[maxn];
12 bool tmp[maxn][2];
13 char a[maxn],b[maxn];
14
15 struct Node
16 {
17 int val;
18 int color;
19 int tree[26];
20 };
21 Node z[maxn];
22 int tot, root;
23
24 int newnode()
25 {
26 z[tot].val = 0;
27 z[tot].color = 0;
28 memset(z[tot].tree, -1, sizeof(z[tot].tree));
29 tot++;
30 return tot-1;
31 }
32
33 //预处理计算next数组
34 void GETNEXT(char *str,int len)
35 {
36 int i=0,j,po;
37 nt[0]=len; //初始化nt[0]
38 while(str[i]==str[i+1]&&i+1<len) i++; //计算nt[1]
39 nt[1]=i;
40 po=1; //初始化po的位置
41 for(i=2;i<len;i++){
42 if(nt[i-po]+i<nt[po]+po) nt[i]=nt[i-po]; //第一种情况,可以直接得到nt[i]的值
43 else{ //第二种情况,要继续匹配才能得到nt[i]的值
44 j=nt[po]+po-i;
45 if(j<0) j=0; //如果i>po+nt[po],则要从头开始匹配
46 while(i+j<len&&str[j]==str[j+i]) j++; //计算nt[i]
47 nt[i]=j;
48 po=i; //更新po的位置
49 }
50 }
51 }
52
53 //计算extend数组
54 void EXKMP(char *s1,int len,char *s2,int l2,int s,int flag) ///s1的后缀和s2的前缀匹配
55 {
56 int i=0,j,po;
57 GETNEXT(s2,len); //计算子串的next数组
58 while(s1[i]==s2[i]&&i<l2&&i<len) i++; //计算ex[0]
59 ex[0]=i;
60 po=0; //初始化po的位置
61 for(i=1;i<len;i++){
62 if(nt[i-po]+i<ex[po]+po) ex[i]=nt[i-po]; //第一种情况,直接可以得到ex[i]的值
63 else{ //第二种情况,要继续匹配才能得到ex[i]的值
64 j=ex[po]+po-i;
65 if(j<0) j=0; //如果i>ex[po]+po则要从头开始匹配
66 while(i+j<len&&j<l2&&s1[j+i]==s2[j]) j++; //计算ex[i]
67 ex[i]=j;
68 po=i; //更新po的位置
69 }
70 }
71 for(int i=0;i<l2;i++)
72 if(ex[i]+i==l2) tmp[i+s][flag]=1;
73 }
74
75 void insert(char *a,int len,int s)
76 {
77 int p=root;
78 for(int i=0;i<len;i++){
79 int c=a[i]-'a';
80 z[p].val+=tmp[i+s][0];
81 if(z[p].tree[c]==-1) {
82 z[p].tree[c]=newnode();
83 }
84 p=z[p].tree[c];
85 }
86 z[p].color++;
87 }
88
89 int query(char *a,int len,int s)
90 {
91 int p=root;
92 ll ans=0;
93 for(int i=0;i<len;i++){
94 int c=a[i]-'a';
95 p=z[p].tree[c];
96 if(p==-1) break;
97 if((i<len-1&&tmp[s+i+1][1])||i==len-1) ans+=z[p].color;
98 }
99 if(p!=-1) ans+=z[p].val;
100 return ans;
101 }
102
103 int main()
104 {
105 ios::sync_with_stdio(false);
106 cin.tie(0);
107 cout.tie(0);
108 int t;
109 cin>>t;
110 int l=0;
111 tot=0;
112 root=newnode();
113 for(int i=0;i<t;i++){
114 cin>>len[i]>>a+l;
115 be[i]=l;
116 l+=len[i];
117 for(int j=0;j<len[i];j++){
118 b[j+be[i]]=a[l-1-j];
119 }
120 EXKMP(a+be[i],len[i],b+be[i],len[i],be[i],0);
121 EXKMP(b+be[i],len[i],a+be[i],len[i],be[i],1);
122 insert(a+be[i],len[i],be[i]);
123 }
124 ll ans=0;
125 for(int i=0;i<t;i++){
126 ans+=query(b+be[i],len[i],be[i]);
127 }
128 cout<<ans<<endl;
129 return 0;
130 }
POJ - 3376 Finding Palindromes(拓展kmp+trie)的更多相关文章
- 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(扩展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 3376 Finding Palindromes (tire树+扩展kmp)
很不错的一个题(注意string会超时) 题意:给你n串字符串,问你两两匹配形成n*n串字符串中有多少个回文串 题解:我们首先需要想到多串字符串存储需要trie树(关键),然后我们正序插入倒序匹配就可 ...
- POJ 3376 Finding Palindromes EX-KMP+字典树
题意: 给你n个串串,每个串串可以选择和n个字符串拼接(可以自己和自己拼接),问有多少个拼接后的字符串是回文. 所有的串串长度不超过2e6: 题解: 这题由于是在POJ上,所以string也用不了,会 ...
- POJ - 3376 Finding Palindromes manacher+字典树
题意 给n个字符串,两两拼接,问拼接后的\(n\times n\)个字符串中有多少个回文串. 分析 将所有正串插入字典树中,马拉车跑出所有串哪些前缀和后缀为回文串,记录位置,用反串去字典树中查询,两字 ...
- poj3376 Finding Palindromes【exKMP】【Trie】
Finding Palindromes Time Limit: 10000MS Memory Limit: 262144K Total Submissions:4710 Accepted: 8 ...
- Seek the Name, Seek the Fame POJ - 2752(拓展kmp || kmp)
题意: 就是求前缀和后缀相同的那个子串的长度 然后从小到大输出 解析: emm...网上都用kmp...我..用拓展kmp做的 这就是拓展kmp板题嘛... 求出extend数组后 把exten ...
随机推荐
- 解放双手,markdown文章神器,Typora+PicGo+七牛云图床实现自动上传图片
本文主要分享使用Typora作为Markdown编辑器,PicGo为上传图片工具,使用七牛云做存储来解放双手实现图片的自动化上传与管理.提高写作效率,提升逼格.用过 Markdown 的朋友一定会深深 ...
- CSS卡片旋转
html{ perspective: 800px; } body{ display:flex; flex-wrap: wrap; } .card{ transform-style: preserve- ...
- 一网打尽,一文讲通虚拟机VirtualBox及Linux使用
本文将从虚拟机的选择.安装.Linux系统安装.SSH客户端工具使用四个方面来详细介绍Linux系统在虚拟机下的安装及使用方法,为你在虚拟机下正常使用Linux保驾护航. 1.虚拟机的选择 在讲虚拟机 ...
- FastApi学习(二)
前言 继续学习 此为第二篇, 还差些知识点就可以结束, 更多的比如用户的身份校验/ swagger 文档修改等以后会单独写 正文 使用枚举来限定参数 可以使用枚举的方式来限定参数为某几个值之内才通过 ...
- 面试官:你真的了解Redis分布式锁吗?
什么是分布式锁 说到Redis,我们第一想到的功能就是可以缓存数据,除此之外,Redis因为单进程.性能高的特点,它还经常被用于做分布式锁. 锁我们都知道,在程序中的作用就是同步工具,保证共享资源在同 ...
- Spring源码深度解析之事务
Spring源码深度解析之事务 目录 一.JDBC方式下的事务使用示例 (1)创建数据表结构 (2)创建对应数据表的PO (3)创建表和实体之间的映射 (4)创建数据操作接口 (5)创建数据操作接口实 ...
- 简单解析一下 Mybatis 常用的几个配置
目录 核心配置文件 环境配置(environments) 属性(properties) 类型别名(typeAliases) 映射器(mappers) Mybatis 参考:https://mybati ...
- DOCKER 安装步骤-最靠谱的笔记
一.系统环境规划 服务器名 项目名称 docker 操作系统 CentOS Linux release 7.1.1503 (Core) Docker 版本 17.03.2-ce 二.Docker ...
- 使用idea插件识别log文件的相关设置
最近要读一些spring boot项目产生的log文件,众所周知,idea拥有强大的插件系统.当我打开log文件时,idea自动帮我推荐了ideolog这个插件. 但是当我安装好之后发现系统并不能完全 ...
- 数据分析——Numpy/pandas
NumPy NumPy是高性能科学计算和数据分析的基础包.部分功能如下: ndarray, 具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组. 用于对整组数据进行快速运算的标准数学函数(无需编 ...