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中, 若在匹配串时遇上在这个结点结束的字符串, 那么看剩下的后缀是否是回文, 若是, 则把在该点结束的字符串数目累加到答案。
将所有的字符串都放在一个数组里,用一个数组记录每个串的起点,这样能节省空间。
1 #include<iostream>2 #include<algorithm>3 #include<string.h>4 #define ll long long5 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 Node16 {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(扩展kmp+trie)
题目链接:http://poj.org/problem?id=3376 题意:给你n个字符串m1.m2.m3...mn 求S = mimj(1=<i,j<=n)是回文串的数量 思路:我们考 ...
- POJ3376 Finding Palindromes
目录 知识点:Trie树(字典树).拓展kmp(manacher?).时间空间复杂度 题目 输入 输出 样例 输入 输出 提示 题意 思路 代码 知识点:Trie树(字典树).拓展kmp(manach ...
- 模板:拓展kmp(Z函数)
所谓拓展kmp,就是拓展的kmp (逃) 前言 小清新算法,更像一个trick. exkmp能够在线性复杂度内求出字符串所有后缀与字符串本身的lcp. 个人感觉这个东西和kmp关系不大,反而有些像马拉 ...
- 【总结】字符串匹配: KMP 和 拓展KMP
比起ac自动机,kmp就一个next数组,理解了如何初始化next后就可以搞一些模板题了,下面是还不错的学习资料,清晰易懂,自己用的模板也来自它: http://chaoswork.com/blog/ ...
- zoj 3587 Marlon's String(拓展KMP+dp)
链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3587 题目大意: 给字符串S,T, 找到所有的tetrad ( ...
- 拓展kmp(2020新年第一篇博客 学无止境冲啊)
拓展kmp算法可解决以下问题,给定两个字符串s1和s2,可以求出s1的extend数组(简记为ex),其中extend[i]表示s1从第i位开始的子串和s2的最大公共前缀长度,举个例子:可以看到ext ...
- HDU - 4333 Revolving Digits 拓展KMP
传送门:点击打开链接 一个长度为lent的串T最多可以构造出lent个数字,所以这道题目的难点在于如何快速的将构造出的数字和原数字进行比较. 将两个T串合并成一个大的S串,构造出的数字实际上就是S的每 ...
- KMP Trie 例题讲解
文章目录 HDU 4763 Theme Section 题意: 题解: 代码: POJ 3630 Phone List 题意: 题解: 代码: HDU 3746 Cyclic Nacklace 题意: ...
- POJ 3461 字符串匹配(KMP / 哈希(有推导))
文章目录 1. 题目 1.1 题目链接 1.2 题目大意 2. Accepted代码 2.1 KMP解法 2.2 哈希法(有推导过程) 1. 题目 1.1 题目链接 http://poj.org/pr ...
- poj 3080-Blue Jeans(暴力KMP)
传送门: poj 3080 题意: 给出一系列长度为60的字符串,让求出它们的最大的公共子序列 题解: 1.既然是公共子序列,那么在其中一个数据里面可能会有一个子串是满足条件的,那么我们可以将其中的一 ...
最新文章
- android camera之nv21旋转
- wagtail python cms 测试部署
- 实战tcpdump看RST
- PHPUnit 3.4.10 在windows上配置
- 《剑指offer》和为s的两个数字
- 差点就被联通客服给营销了...
- [Swift]LeetCode916.单词子集 | Word Subsets
- css专业名词,CSS进阶系列一(flex布局基础知识——介绍、规范、主要思想、专业术语)...
- 【httpClient】Timeout waiting for connection from pool
- java transient关键字_嗯?你真的会用 Java 序列化机制?
- 【shell 练习5】编写简单的多级菜单
- 车载系统华山论剑:Ali OS、Android、QNX孰优孰劣
- 情人节程序员用HTML网页表白【浪漫爱心旋转】 HTML5七夕情人节表白网页源码 HTML+CSS+JavaScript
- java实现数据库自动异地备份
- 【JAVA程序设计】(C00019)javaweb高校社团管理系统
- matlab图像取反_MATLAB图像处理例子
- 【搞定Go语言】第3天22:常用的HTTP服务压测工具介绍
- C语言版本STFT/ISTFT
- C 语言do with,Nonverbal (非语言的) communication has to do with gestures, movements andcloseness of two...
- 设置TextView滚动
热门文章
- ZA7783是一颗将单路MIPI DSI信号转换成单路LVDS/TTL信号的转接芯片
- [密码学复习]Cryptography
- 如何查看电脑连过的WIFI以及WiFi密码
- 如何让Loadrunner或Jmeter发送邮件报告
- chrome打不开网页 转圈圈
- T 型与π型衰减网络
- ESP8266-Arduino编程实例-MPL3115A2压力传感器驱动
- 百度云网盘一直显示“下载请求中”,一个 解决办法
- mysql 误删表 恢复数据_MySQL误删数据或者误清空表恢复
- python123随机密码生成_Python生成对应随机密码文件