题目传送门

题目大意:给你一个字符串,让你求出有多少对相交的回文子串

啊啊啊啊降智了,我怎么又忘了正难则反

求相交会很难搞。把问题转化成求互不相交的回文子串再减一下就行了

先利用$PAM$求出以每个位置为末尾的回文子串数量,这个数量就是此时构造末尾节点在$fail$树中的深度

再把串翻过来,用同样的方法求出每个位置为开头的回文子串数量

对其中一个数组求前缀和,用乘法原理算一下就行了

空间开不下怎么办?以时间换空间,用邻接表存儿子!每次跳儿子都暴力遍历一次邻接表

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #define ll long long
  5. #define N1 2000010
  6. using namespace std;
  7. const int p=;
  8.  
  9. template <typename _T> void read(_T &ret)
  10. {
  11. ret=; _T fh=; char c=getchar();
  12. while(c<''&&c>''){ if(c=='-') fh=-; c=getchar(); }
  13. while(c>=''&&c<=''){ ret=ret*+c-''; c=getchar(); }
  14. ret=ret*fh;
  15. }
  16. /*void exgcd(ll a,ll b,ll &x,ll &y)
  17. {
  18. if(!b){ x=1; y=0; return; }
  19. exgcd(b,a%b,x,y); ll t=x; x=y; y=t-a/b*y;
  20. }*/
  21.  
  22. int idx(char c){ return c-'a'; }
  23.  
  24. struct Edge{
  25. int to[N1],nxt[N1],val[N1],head[N1],cte;
  26. void ae(int u,int v,int w)
  27. { cte++; to[cte]=v; nxt[cte]=head[u]; val[cte]=w; head[u]=cte; }
  28. }e;
  29.  
  30. namespace PAM{
  31. int pre[N1],dep[N1],sum[N1],sz[N1],la,tot;
  32. void clr()
  33. {
  34. memset(pre,,sizeof(pre)); memset(dep,,sizeof(dep));
  35. memset(sum,,sizeof(sum)); memset(&e,,sizeof(e));
  36. }
  37. void init(){ la=tot=; pre[]=pre[]=; dep[]=-; }
  38. int same(char *str,int p,int i){ return str[i-dep[p]-]==str[i]; }
  39. int trs(int x,int c)
  40. {
  41. for(int j=e.head[x];j;j=e.nxt[j])
  42. if(e.val[j]==c) return e.to[j];
  43. return ;
  44. }
  45. int insert(char *str,int i)
  46. {
  47. int p=la,np,fp,tp,c=idx(str[i]);
  48. while(!same(str,p,i)) p=pre[p];
  49. if(!(tp=trs(p,c))) //!trs[p][c]
  50. {
  51. np=++tot;
  52. dep[np]=dep[p]+;
  53. fp=pre[p];
  54. while(!same(str,fp,i)) fp=pre[fp];
  55. pre[np]=trs(fp,c); //trs[fp][c]
  56. e.ae(p,np,c); //trs[p][c]=np;
  57. p=np;
  58. }else p=tp;
  59. la=p;
  60. sum[p]=sum[pre[p]]+;
  61. return p;
  62. }
  63. };
  64.  
  65. int n;
  66. char str[N1];
  67. ll lsum[N1],rsum[N1];
  68.  
  69. int main()
  70. {
  71. int i,j,x; ll ans=;
  72. scanf("%d",&n);
  73. scanf("%s",str+);
  74. PAM::init();
  75. for(i=;i<=n;i++) x=PAM::insert(str,i), lsum[i]=PAM::sum[x];// ans+=lsum[i];
  76. PAM::clr(); PAM::init();
  77. reverse(str+,str+n+);
  78. for(i=;i<=n;i++) x=PAM::insert(str,i), rsum[i]=PAM::sum[x], rsum[i]+=rsum[i-]; //rsum[i]+=rsum[i-1];
  79. if(rsum[n]&) ans=1ll*((rsum[n]-)/%p)*(rsum[n]%p)%p;
  80. else ans=1ll*(rsum[n]/%p)*((rsum[n]-)%p)%p;
  81. for(i=;i<=n;i++) ans=(ans-1ll*lsum[i-]*rsum[n-i+]%p+p)%p;
  82. printf("%I64d\n",(ans%p+p)%p);
  83. return ;
  84. }

CF17E Palisection (回文自动机+DP)的更多相关文章

  1. bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp)

    bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp) bzoj Luogu 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一 ...

  2. bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp)

    bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp) bzoj Luogu 你要用ATGC四个字母用两种操作拼出给定的串: 1.将其中一个字符 ...

  3. 洛谷P4762 [CERC2014]Virus synthesis(回文自动机+dp)

    传送门 回文自动机的好题啊 先建一个回文自动机,然后记$dp[i]$表示转移到$i$节点代表的回文串的最少的需要次数 首先肯定2操作越多越好,经过2操作之后的串必定是一个回文串,所以最后的答案肯定是由 ...

  4. bzoj 4044: [Cerc2014] Virus synthesis【回文自动机+dp】

    建回文自动机,注意到一个回文串是可以通过一个长度小于等于这个串长度的一半的回文串添上一些字符然后复制得到的,也就是在自动机上向fa走,相当于treedp 每次都走显然会T,记录一个up,指向祖先中最下 ...

  5. [CERC2014]Virus synthesis【回文自动机+DP】

    [CERC2014]Virus synthesis 初始有一个空串,利用下面的操作构造给定串 SS . 1.串开头或末尾加一个字符 2.串开头或末尾加一个该串的逆串 求最小化操作数, \(|S| \l ...

  6. BZOJ 4044 Virus synthesis (回文自动机+dp)

    题目大意: 你可以在一个串的开头或者末尾加入一个字符,或者把当前整个串$reverse$,然后接在前面或者后面,求达到目标串需要的最少操作次数 对目标串建出$PAM$ 定义$dp[x]$表示当前在回文 ...

  7. [BZOJ4044]Virus synthesis 回文自动机的DP

    4044: [Cerc2014] Virus synthesis Time Limit: 20 Sec  Memory Limit: 128 MB Description Viruses are us ...

  8. BZOJ 4044 Luogu P4762 [CERC2014]Virus Synthesis (回文自动机、DP)

    好难啊..根本不会做..基本上是抄Claris... 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4044 (luogu) ...

  9. BZOJ 3790 神奇项链(回文自动机+线段树优化DP)

    我们预处理出来以i为结尾的最长回文后缀(回文自动机的构建过程中就可以求出)然后就是一个区间覆盖,因为我懒得写贪心,就写了线段树优化的DP. #include<iostream> #incl ...

随机推荐

  1. BC - Zball in Tina Town (质数 + 找规律)

    Zball in Tina Town  Accepts: 541  Submissions: 2463  Time Limit: 3000/1500 MS (Java/Others)  Memory ...

  2. MBLAST - BLAST

    There are given two strings, A and B. An expansion of some string X is a string created by adding or ...

  3. ubuntu安装phpstorm

    首先要安装jdk $ java -version java version "1.8.0_171" Java(TM) SE Runtime Environment (build 1 ...

  4. P2597 [ZJOI2012]灾难 拓扑排序

    这个题有点意思,正常写法肯定会T,然后需要优化.先用拓扑排序重构一遍树,然后进行一个非常神奇的操作:把每个点放在他的食物的lca上,然后计算的时候直接dfs全加上就行了.为什么呢,因为假如你的食物的l ...

  5. 互斥的数(hash)

    1553 互斥的数  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold     题目描述 Description 有这样的一个集合,集合中的元素个数由给定的N决定, ...

  6. 【TIDB】1、TiDb简介

    一 TiDb简介 TiDB 是 PingCAP 公司受 Google Spanner / F1 论文启发而设计的开源分布式 HTAP (Hybrid Transactional and Analyti ...

  7. JavaScript学习四

    2019-06-01 09:09:23 坚持,加油!!! 函数的学习 <html> <head> <script type="text/javascript&q ...

  8. javascript中for...in和for...of的区别

    for...of循环是ES6引入的新的语法. for...in遍历拿到的x是键(下标).而for...of遍历拿到的x是值,但在对象中会提示不是一个迭代器报错.例子如下: let x; let a = ...

  9. python自动化测试学习笔记-6urllib模块&request模块

    python3的urllib 模块提供了获取页面的功能. urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capat ...

  10. JavaScript--什么是函数

    函数是完成某个特定功能的一组语句.如没有函数,完成任务可能需要五行.十行.甚至更多的代码.这时我们就可以把完成特定功能的代码块放到一个函数里,直接调用这个函数,就省重复输入大量代码的麻烦. 如何定义一 ...