题解 \(by\;zj\varphi\)

考虑对于母串的每个字符,它在匹配串中有多少前缀,多少后缀。

设 \(f_i\) 表示 \(i\) 位置匹配上的前缀,\(g_i\) 为后缀,那么答案为 \(\sum_{i=1}^{len}f_i×g_i\)

那么如何求出 \(f_i\) 和 \(g_i\),考虑二分,求出一个最长的前缀,后缀。

在初始化时,将所有后缀记录上它的子后缀,前缀同理,用 \(trie\) 树就行,记得用 unordered_map

Code:
  1. #include<bits/stdc++.h>
  2. #define ri register signed
  3. #define p(i) ++i
  4. using namespace std;
  5. namespace IO{
  6. char buf[1<<21],*p1=buf,*p2=buf,OPUT[100];
  7. #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1<<21,1,stdin),p1==p2)?(-1):*p1++
  8. template<typename T>inline void read(T &x) {
  9. ri f=1;x=0;register char ch=getchar();
  10. while(!isdigit(ch)) {if (ch=='-') f=0;ch=getchar();}
  11. while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  12. x=f?x:-x;
  13. }
  14. template<typename T>inline void print(T x) {
  15. if (x<0) putchar('-'),x=-x;
  16. if (!x) return putchar('0'),(void)putchar('\n');
  17. ri cnt(0);
  18. while(x) OPUT[p(cnt)]=x%10,x/=10;
  19. for (ri i(cnt);i;--i) putchar(OPUT[i]^48);
  20. return (void)putchar('\n');
  21. }
  22. }
  23. using IO::read;using IO::print;
  24. namespace nanfeng{
  25. #define FI FILE *IN
  26. #define FO FILE *OUT
  27. template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
  28. template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
  29. typedef unsigned long long ull;
  30. typedef long long ll;
  31. static const int N=1e5+7,P=131,L=2e5+7;
  32. int len1,len,n;
  33. ll ans;
  34. char s[N],s1[N];
  35. ull p[N],h[N];
  36. unordered_map<ull,int> mp1,mp2;
  37. struct Trie{
  38. #define Son(x,p) T[x].ch[p]
  39. struct trie{int ch[26],nm;}T[L];
  40. int tot;
  41. Trie(){tot=1;}
  42. inline void insert() {
  43. ri cur=1;
  44. for (ri i(1);i<=len;p(i)) {
  45. ri ch=s[i]-'a';
  46. if (!Son(cur,ch)) Son(cur,ch)=p(tot);
  47. cur=Son(cur,ch);
  48. p(T[cur].nm);
  49. }
  50. }
  51. void dfs1(int nw,ull h) {
  52. if (nw!=1&&T[nw].nm) mp1[h]=T[nw].nm;
  53. for (ri i(0);i<26;p(i))
  54. if (Son(nw,i)) {
  55. T[Son(nw,i)].nm+=T[nw].nm;
  56. dfs1(Son(nw,i),(ull)(i+1)+h*P);
  57. }
  58. }
  59. void dfs2(int nw,ull h,int dep) {
  60. if (nw!=1&&T[nw].nm) mp2[h]=T[nw].nm;
  61. for (ri i(0);i<26;p(i))
  62. if (Son(nw,i)) {
  63. T[Son(nw,i)].nm+=T[nw].nm;
  64. dfs2(Son(nw,i),(ull)(i+1)*p[dep]+h,dep+1);
  65. }
  66. }
  67. }T1,T2;
  68. inline int main() {
  69. //FI=freopen("nanfeng.in","r",stdin);
  70. //FO=freopen("nanfeng.out","w",stdout);
  71. p[0]=1;
  72. for (ri i(1);i<=N-7;p(i)) p[i]=p[i-1]*P;
  73. scanf("%s",s1+1);
  74. len1=strlen(s1+1);
  75. for (ri i(1);i<=len1;p(i)) h[i]=h[i-1]*P+(ull)(s1[i]-'a'+1);
  76. read(n);
  77. ull k=-1;
  78. for (ri i(1);i<=n;p(i)) {
  79. scanf("%s",s+1);
  80. len=strlen(s+1);
  81. T1.insert();
  82. reverse(s+1,s+len+1);
  83. T2.insert();
  84. }
  85. T1.dfs1(1,0),T2.dfs2(1,0,0);
  86. for (ri i(1);i<len1;p(i)) {
  87. ri l(1),r(i),res(-1),tmp1(0),tmp2(0);
  88. while(l<=r) {
  89. int mid(l+r>>1);
  90. if (mp2.find(h[i]-h[i-mid]*p[mid])!=mp2.end()) l=mid+1,res=mid;
  91. else r=mid-1;
  92. }
  93. if (res!=-1) tmp2=mp2[h[i]-h[i-res]*p[res]];
  94. l=1,r=len1-i,res=-1;
  95. while(l<=r) {
  96. int mid(l+r>>1);
  97. if (mp1.find(h[i+mid]-h[i]*p[mid])!=mp1.end()) l=mid+1,res=mid;
  98. else r=mid-1;
  99. }
  100. if (res!=-1) tmp1=mp1[h[i+res]-h[i]*p[res]];
  101. ans+=1ll*tmp1*tmp2;
  102. }
  103. print(ans);
  104. return 0;
  105. }
  106. }
  107. int main() {return nanfeng::main();}

NOIP 模拟 $25\; \rm string$的更多相关文章

  1. NOIP 模拟 $25\; \rm random$

    题解 \(by\;zj\varphi\) 期望好题. 通过推规律可以发现每个逆序对的贡献都是 \(1\),那么在所有排列中有多少逆序对,贡献就是多少. \[\rm num_i=(i-1)!\sum_{ ...

  2. NOIP 模拟 $25\; \rm queen$

    题解 \(by\;zj\varphi\) 这是一道纯分类讨论,然后推式子的题,细节挺多,挺麻烦,但是很考验数学能力 不讲了,官方题解给的很清楚 Code: %: pragma GCC optimize ...

  3. 7.25 NOIP模拟8

    这次考试前面状态还行,后两个小时真是一言难尽,打了个T3的n^2暴力就懵逼了,不知道怎么优化. T1.匹配 看了一边题发现不太懂(这不是考试的难度啊),然后水完T2后回来5分钟水过,非常愉快的一道题. ...

  4. NOIP模拟 1

    NOIP模拟1,到现在时间已经比较长了.. 那天是6.14,今天7.18了 //然鹅我看着最前边缺失的模拟1,还是终于忍不住把它补上,为了保持顺序2345重新发布了一遍.. #   用  户  名   ...

  5. 2021.5.22 noip模拟1

    这场考试考得很烂 连暴力都没打好 只拿了25分,,,,,,,,好好总结 T1序列 A. 序列 题目描述 HZ每周一都要举行升旗仪式,国旗班会站成一整列整齐的向前行进. 郭神作为摄像师想要选取其中一段照 ...

  6. NOIP 模拟 $30\; \rm 毛一琛$

    题解 \(by\;zj\varphi\) 如何判断一个集合可以被拆成两个相等的部分? 枚举两个集合,如果它们的和相等,那么他们的并集就是合法的,复杂度 \(\mathcal O\rm(3^n)\) \ ...

  7. NOIP模拟3

    期望得分:30+90+100=220 实际得分:30+0+10=40 T1智障错误:n*m是n行m列,硬是做成了m行n列 T2智障错误:读入三个数写了两个%d T3智障错误:数值相同不代表是同一个数 ...

  8. 7.22 NOIP模拟7

    又是炸掉的一次考试 T1.方程的解 本次考试最容易骗分的一道题,但是由于T2花的时间太多,我竟然连a+b=c都没判..暴力掉了40分. 首先a+b=c,只有一组解. 然后是a=1,b=1,答案是c-1 ...

  9. NOIP模拟 9

    %liu_runda Orz T1 随 矩阵快速幂结合概率期望 但n3无法承受 利用原根的性质,将乘法转化成加法 就变成循环矩阵n^2了 改题时苦b地卡了关:误把1当成原根的1次方,错误地认为矩阵的阶 ...

随机推荐

  1. buu Youngter-drive

    一.查壳,发现是upx的壳,用自解压方式,脱下壳 二.之后发现打不开了,应该是要修复,不想修复了,直接拖入ida 找到关键函数,中间发生一点小插曲,发现堆栈不平衡,然后导致F5反编译失败,百度了下是A ...

  2. buu SimpleRev

    一.发现是elf文件,拖入ida,然后直接找到了关键函数 点击那个Decry()函数 二.逻辑还是很清晰的,而我是卡在这里v1的逆算法,感觉学到了很多,其实爆破就足够了 这里大小写可以一起写上 tex ...

  3. Oracle如何以逗号分隔的字符串拆分为多行数据

    近期在工作中遇到某表某字段是可扩展数据内容,信息以逗号分隔生成的,现需求要根据此字段数据在其它表查询相关的内容展现出来,第一想法是切割数据,以逗号作为切割符,以下为总结的实现方法,以供大家参考.指教. ...

  4. F5负载均衡-配置指导手册(含IPv6)

    F5负载均衡-配置手册 设备概况 图形化界面 通过网络形式访问F5任一接口地址,打开浏览器输入https://网络接口地址:或pc机直连F5的MGMT带外管理口,打开浏览器,输入https://192 ...

  5. [转载]实现DDOS攻击自动封禁IP

    1 #!/bin/bash 2 ############################################################# 3 # File Name: ddos_ch ...

  6. python使用笔记26--多线程、多进程

    1.概念 线程.进程 进程是资源的集合,也就是一个程序 线程是一个程序运行的最小单位 线程是在进程里面的 默认,一个进程就只有一个线程 一个电脑有几核CPU就只能同时运行几个任务,比如4核CPU只能同 ...

  7. C语言:源代码兼容WINDOWS LINUX

    使用库函数之前,应该用#include引入对应的头文件.这种以#号开头的命令称为预处理命令.C语言源文件要经过编译.链接才能生成可执行程序:1) 编译(Compile)会将源文件(.c文件)转换为目标 ...

  8. python twain模块

    >>> help(twain) Help on module twain: NAME twain - Created on Sep 4, 2011 DESCRIPTION @auth ...

  9. [004] .NET 的现状和未来

    我们总是能听到一些人说,.NET 不行.学 .NET 没发展前途之类的言论,有的童鞋听多了便也开始怀疑自己选择的 .NET 方向是不是错了. 不得不承认,在 .NET 没有实现跨平台之前,市场行情确实 ...

  10. sql-2-DDL

    DDL-定义数据库 1.对database操作 1.创建数据库 create database [if not exist] 库名; CREATE DATABASE `shop` CHARACTER ...