题目大意:有 N 个字符串,所有的字符串长度不超过 200W 任意俩俩字符串可以自由组合,问组合的字符串是回文串的个数有多少个?
 
分析:这是一个相当猥琐的字符串处理,因为没有说单个的字符串最少多长,所以很可能会有这样的情况,200w个字符串,每个字符串长度1,或者1个串,这个串的长度是100w, 为了对付这种猥琐的方式可以用一个长为100w的字符串保存所有的串,然后用另一个数组记录每个字符串所在的区间。匹配的时候可以使用trie因为回文串是两端匹配,所以插入trie的时候可以倒着插入,不过查询的时候会出现两种情况,一种是这个字符串已经匹配完,不过他后面匹配的字符串没有完,另一种是这个字符串匹配完还有剩余长度,不管哪种情况都需要判断一下剩余的串是否是回文串,tire里面的保存后缀,匹配串保存的是前缀。
 
代码如下:
================================================================================================================
  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. using namespace std;
  5.  
  6. const int MAXN = 2e6+;
  7. const int oo = 1e9+;
  8.  
  9. struct Trie
  10. {///字典树的节点
  11. int next[];
  12. int leaf;///以这个节点为终点的叶子节点个数
  13. int count;///后面回文串的数量
  14.  
  15. void Free()
  16. {
  17. leaf = count = ;
  18. memset(next, false, sizeof(next));
  19. }
  20.  
  21. }trie[MAXN];
  22.  
  23. int top;///配合字典树使用,top表示没有使用的内存
  24. int start[MAXN], p[MAXN<<];
  25. char MumStr[MAXN], Estr[MAXN<<];
  26. bool suffix[MAXN];///后缀是否是回文串
  27. bool prefix[MAXN];///前缀是否是回文串
  28.  
  29. void BuildTrie(int n)
  30. {
  31. int p = ;
  32.  
  33. for(int i=start[n+]-; i>=start[n]; i--)
  34. {///把字符串倒插进去
  35. int k = MumStr[i] - 'a';
  36.  
  37. trie[p].count += prefix[i];
  38.  
  39. if(trie[p].next[k] == )
  40. {
  41. trie[p].next[k] = ++top;
  42. trie[top].Free();
  43. }
  44. p = trie[p].next[k];
  45. }
  46.  
  47. trie[p].leaf += ;
  48. }
  49. void Manacher(int n)
  50. {
  51. int i, id=, len=;
  52.  
  53. Estr[] = '$';
  54.  
  55. for(i=start[n]; i<start[n+]; i++)
  56. {
  57. Estr[len++] = '#';
  58. Estr[len++] = MumStr[i];
  59.  
  60. suffix[i] = false;
  61. prefix[i] = false;
  62. }
  63. Estr[len] = '#';
  64. Estr[len+] = ;
  65.  
  66. for(i=; i<len; i++)
  67. {
  68. p[i] = ;
  69.  
  70. if(p[id]+id > i)
  71. p[i] = min(p[id*-i], p[id]+id-i);
  72.  
  73. while(Estr[ i+p[i] ] == Estr[ i-p[i] ])
  74. p[i]++;
  75.  
  76. if(p[id]+id < p[i]+i)
  77. id = i;
  78.  
  79. if(p[i] == i)
  80. prefix[ start[n]+p[i]- ] = true;
  81. if(p[i]+i- == len)
  82. suffix[ start[n+]-p[i]+ ] = true;
  83. }
  84. }
  85. int Query(int n)
  86. {
  87. int i, p=, sum = ;
  88.  
  89. for(i=start[n]; i<start[n+]; i++)
  90. {
  91. int k = MumStr[i] - 'a';
  92.  
  93. if(trie[p].next[k] == )
  94. break;
  95.  
  96. p = trie[p].next[k];
  97.  
  98. if(suffix[i+] || i==start[n+]-)
  99. sum += trie[p].leaf;
  100. }
  101.  
  102. if(i == start[n+])
  103. sum += trie[p].count;
  104.  
  105. return sum;
  106. }
  107.  
  108. int main()
  109. {
  110. int N;
  111.  
  112. while(scanf("%d", &N) != EOF)
  113. {
  114. int i, len;
  115.  
  116. top = ;
  117. trie[].Free();
  118.  
  119. for(i=; i<=N; i++)
  120. {
  121. scanf("%d%s", &len, MumStr+start[i]);
  122. start[i+] = start[i] + len;
  123.  
  124. Manacher(i);
  125. BuildTrie(i);
  126. }
  127.  
  128. long long ans = ;
  129.  
  130. for(i=; i<=N; i++)
  131. ans += Query(i);
  132.  
  133. printf("%lld\n", ans);
  134. }
  135.  
  136. return ;
  137. }
  138. /**
  139. 2
  140. 3 abc
  141. 4 acba
  142.  
  143. */

Finding Palindromes - 猥琐的字符串(Manacher+trie)的更多相关文章

  1. POJ 3376 Finding Palindromes(manacher求前后缀回文串+trie)

    题目链接:http://poj.org/problem?id=3376 题目大意:给你n个字符串,这n个字符串可以两两组合形成n*n个字符串,求这些字符串中有几个是回文串. 解题思路:思路参考了这里: ...

  2. poj3376 Finding Palindromes【exKMP】【Trie】

    Finding Palindromes Time Limit: 10000MS   Memory Limit: 262144K Total Submissions:4710   Accepted: 8 ...

  3. POJ3376 Finding Palindromes —— 扩展KMP + Trie树

    题目链接:https://vjudge.net/problem/POJ-3376 Finding Palindromes Time Limit: 10000MS   Memory Limit: 262 ...

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

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

  5. poj 3376 Finding Palindromes

    Finding Palindromes http://poj.org/problem?id=3376 Time Limit: 10000MS   Memory Limit: 262144K       ...

  6. PHP后门新玩法:一款猥琐的PHP后门分析

    0x00 背景 近日,360网站卫士安全团队近期捕获一个基于PHP实现的webshell样本,其巧妙的代码动态生成方式,猥琐的自身页面伪装手法,让我们在分析这个样本的过程中感受到相当多的乐趣.接下来就 ...

  7. 模板—字符串—Manacher

    模板—字符串—Manacher Code: #include <cstdio> #include <cstring> #include <algorithm> us ...

  8. delphi之猥琐的webserver实现

    http://www.birdol.com/cainiaobiancheng/238.html delphi之猥琐的webserver实现 菜鸟编程  十五楼的鸟儿  7年前 (2009-01-01) ...

  9. 牛客练习赛11 假的字符串 (Trie树+拓扑找环)

    牛客练习赛11 假的字符串 (Trie树+拓扑找环) 链接:https://ac.nowcoder.com/acm/problem/15049 来源:牛客网 给定n个字符串,互不相等,你可以任意指定字 ...

随机推荐

  1. 关于cocoapods和swift中使用oc第三方

    mac 系统自带ruby,使用cocoapods,直接安装cocoapods就行 终端:$ sudo gem install cocoapods {安装较慢是因为有墙,查看ruby镜像列表:$ gem ...

  2. 类和ID选择器的区别

    学习了类选择器和ID选择器,我们会发现他们之间有很多的相似处,是不是两者可以通用呢?我们不要着急先来总结一下他们的相同点和不同点: 相同点:可以应用于任何元素不同点: 1.ID选择器只能在文档中使用一 ...

  3. 外部式css样式,写在单独的一个文件中

    外部式css样式(也可称为外联式)就是把css代码写一个单独的外部文件中,这个css样式文件以“.css”为扩展名,在<head>内(不是在<style>标签内)使用<l ...

  4. [转载]hadoop SecondNamenode详解

    SecondNamenode名字看起来很象是对第二个Namenode,要么与Namenode一样同时对外提供服务,要么相当于Namenode的HA.真正的了解了SecondNamenode以后,才发现 ...

  5. csv文本编辑引号问题

    今天发现一个csv的一个问题,csv工具类对于引号默认有特殊的处理.我希望写出来的结果是 1,"1",1 原来的代码是 CsvWriter cw=new CsvWriter(&qu ...

  6. 不使用ASP.NET服务器端控件(包括form表单不加runat="server")来触发.cs里的事件(方法),(适用于有代码洁癖者)。

    很多时候,我们使用服务器端控件写出的代码,会给我们生成一些很多我们看不懂的代码(初学者),但是有时候我们并不需要这些代码(业务需求不同),对于生成的一些代码感到多余.所以我就开始想,有没有一种可能:不 ...

  7. 关于unitils联合dbunit的测试

    unitils据说测试的能力很强大,可测试dao,service,web层,其实对数据库的测试我更关心,看到有人展示了测试的方法,数据直接写在xls表中,很直观,然后就依照他们的方法进行试验,花费的时 ...

  8. strcpy实现

    #include <iostream> using namespace std; char *strcpy(char *strDest, const char *strSrc) { if ...

  9. ibatis动态语句加and 和不加and

    <select id="queryGoodsGroupCodeName" parameterClass="String" resultClass=&quo ...

  10. MSP430的IO口模拟I2C总线对AT24C25进行读写程序

    功能: 实现MSP430口线模拟I2C总线协议与24C04通信.                                           ** 描述: 主系统工作时钟为12MHz,I2C工 ...