传送门: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)相关推荐

  1. POJ 3376 Finding Palindromes(扩展kmp+trie)

    题目链接:http://poj.org/problem?id=3376 题意:给你n个字符串m1.m2.m3...mn 求S = mimj(1=<i,j<=n)是回文串的数量 思路:我们考 ...

  2. POJ3376 Finding Palindromes

    目录 知识点:Trie树(字典树).拓展kmp(manacher?).时间空间复杂度 题目 输入 输出 样例 输入 输出 提示 题意 思路 代码 知识点:Trie树(字典树).拓展kmp(manach ...

  3. 模板:拓展kmp(Z函数)

    所谓拓展kmp,就是拓展的kmp (逃) 前言 小清新算法,更像一个trick. exkmp能够在线性复杂度内求出字符串所有后缀与字符串本身的lcp. 个人感觉这个东西和kmp关系不大,反而有些像马拉 ...

  4. 【总结】字符串匹配: KMP 和 拓展KMP

    比起ac自动机,kmp就一个next数组,理解了如何初始化next后就可以搞一些模板题了,下面是还不错的学习资料,清晰易懂,自己用的模板也来自它: http://chaoswork.com/blog/ ...

  5. zoj 3587 Marlon's String(拓展KMP+dp)

    链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3587 题目大意: 给字符串S,T,   找到所有的tetrad ( ...

  6. 拓展kmp(2020新年第一篇博客 学无止境冲啊)

    拓展kmp算法可解决以下问题,给定两个字符串s1和s2,可以求出s1的extend数组(简记为ex),其中extend[i]表示s1从第i位开始的子串和s2的最大公共前缀长度,举个例子:可以看到ext ...

  7. HDU - 4333 Revolving Digits 拓展KMP

    传送门:点击打开链接 一个长度为lent的串T最多可以构造出lent个数字,所以这道题目的难点在于如何快速的将构造出的数字和原数字进行比较. 将两个T串合并成一个大的S串,构造出的数字实际上就是S的每 ...

  8. KMP Trie 例题讲解

    文章目录 HDU 4763 Theme Section 题意: 题解: 代码: POJ 3630 Phone List 题意: 题解: 代码: HDU 3746 Cyclic Nacklace 题意: ...

  9. POJ 3461 字符串匹配(KMP / 哈希(有推导))

    文章目录 1. 题目 1.1 题目链接 1.2 题目大意 2. Accepted代码 2.1 KMP解法 2.2 哈希法(有推导过程) 1. 题目 1.1 题目链接 http://poj.org/pr ...

  10. poj 3080-Blue Jeans(暴力KMP)

    传送门: poj 3080 题意: 给出一系列长度为60的字符串,让求出它们的最大的公共子序列 题解: 1.既然是公共子序列,那么在其中一个数据里面可能会有一个子串是满足条件的,那么我们可以将其中的一 ...

最新文章

  1. android camera之nv21旋转
  2. wagtail python cms 测试部署
  3. 实战tcpdump看RST
  4. PHPUnit 3.4.10 在windows上配置
  5. 《剑指offer》和为s的两个数字
  6. 差点就被联通客服给营销了...
  7. [Swift]LeetCode916.单词子集 | Word Subsets
  8. css专业名词,CSS进阶系列一(flex布局基础知识——介绍、规范、主要思想、专业术语)...
  9. 【httpClient】Timeout waiting for connection from pool
  10. java transient关键字_嗯?你真的会用 Java 序列化机制?
  11. 【shell 练习5】编写简单的多级菜单
  12. 车载系统华山论剑:Ali OS、Android、QNX孰优孰劣
  13. 情人节程序员用HTML网页表白【浪漫爱心旋转】 HTML5七夕情人节表白网页源码 HTML+CSS+JavaScript
  14. java实现数据库自动异地备份
  15. 【JAVA程序设计】(C00019)javaweb高校社团管理系统
  16. matlab图像取反_MATLAB图像处理例子
  17. 【搞定Go语言】第3天22:常用的HTTP服务压测工具介绍
  18. C语言版本STFT/ISTFT
  19. C 语言do with,Nonverbal (非语言的) communication has to do with gestures, movements andcloseness of two...
  20. 设置TextView滚动

热门文章

  1. ZA7783是一颗将单路MIPI DSI信号转换成单路LVDS/TTL信号的转接芯片
  2. [密码学复习]Cryptography
  3. 如何查看电脑连过的WIFI以及WiFi密码
  4. 如何让Loadrunner或Jmeter发送邮件报告
  5. chrome打不开网页 转圈圈
  6. T 型与π型衰减网络
  7. ESP8266-Arduino编程实例-MPL3115A2压力传感器驱动
  8. 百度云网盘一直显示“下载请求中”,一个 解决办法
  9. mysql 误删表 恢复数据_MySQL误删数据或者误清空表恢复
  10. python123随机密码生成_Python生成对应随机密码文件