神奇的结论:

一个字符串的所有回文后缀的长度,可以形成\(k\)个等差数列,\(k\)是\(log\)级的

考虑前\(R\)个字符组成的字符串,对于一个等差数列,假设组成这个等差数列的回文串,最短的叫\(a\),最长的叫\(b\) 对于右端点是\(R\)的询问,左端点在\([b\)上一次出现的位置开头\(+1\),\(a\)的开头\(]\)这一段区间的话,\(ans\)要\(+1\)

不会证 自己画了画感觉好像挺对的

知道这个之后只要建出来回文树 询问按右端点排序 每做到一个点回答关于它的询问 最后一次出现的位置用线段树维护 区间加用树状数组维护就做完了

#include<bits/stdc++.h>
using namespace std;
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define pa pair<int,int>
#define mod 1000000007
#define ll long long
#define mk make_pair
#define pb push_back
#define lb double
#define fi first
#define se second
#define cl(x) memset(x,0,sizeof x)
#ifdef Devil_Gary
#define bug(x) cout<<(#x)<<" "<<(x)<<endl
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define bug(x)
#define debug(...)
#endif
const int INF = 0x7fffffff;
const int N=3e5+5;
const int M=1e6+5;
/*
char *TT,*mo,but[(1<<15)+2];
#define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/
inline int read(){
int x=0,rev=0,ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return rev?-x:x;
}
struct Edge{
int v,_nxt;
}e[N];
char s[N];
int head[N],lst,cnt=1,n,m,id,ans[M],Ans,tot,dd[N],c[N][26],L[M],diff[N],fail[N],nxt[N],pre[M],len[N],h[N],in[N],out[N],sum[N],t[N<<2];
int extend(int x,int n){
int p=lst;
while(s[n-len[p]-1]!=s[n]) p=fail[p];
if(!c[p][x]){
int now=++cnt,k=fail[p];
len[now]=len[p]+2;
while(s[n-len[k]-1]!=s[n]) k=fail[k];
fail[now]=c[k][x],c[p][x]=now;
diff[now]=len[now]-len[fail[now]];
if(diff[now]==diff[fail[now]]) nxt[now]=nxt[fail[now]];
else nxt[now]=now;
}
return lst=c[p][x];
}
void add(int u,int v){
e[++tot].v=v,e[tot]._nxt=head[u],head[u]=tot;
}
void build(){
memset(h,0,sizeof h);
for(int i=0;i<=cnt;i++) if(i!=1) add(fail[i],i);
}
void dfs(int x){
in[x]=++id;
for(int i=head[x];i;i=e[i]._nxt){
int j=e[i].v;
dfs(j);
}
out[x]=id;
}
void modify(int pos,int l,int r,int x,int v){
if(l==r) return void(t[pos]=v);
int mid=l+r>>1;
if(x<=mid) modify(pos<<1,l,mid,x,v);
else modify(pos<<1|1,mid+1,r,x,v);
t[pos]=max(t[pos<<1],t[pos<<1|1]);
}
int Query(int pos,int l,int r,int nl,int nr){
if(nl<=l&&r<=nr) return t[pos];
int mid=l+r>>1;
if(nr<=mid) return Query(pos<<1,l,mid,nl,nr);
if(nl>mid) return Query(pos<<1|1,mid+1,r,nl,nr);
return max(Query(pos<<1,l,mid,nl,nr),Query(pos<<1|1,mid+1,r,nl,nr));
}
#define lowbit(x) x&(-x)
void Add(int x,int v){
for(int i=x;i<=n;i+=lowbit(i)) sum[i]+=v;
}
int ask(int x){
int ans=0;
for(int i=x;i;i-=lowbit(i)) ans+=sum[i];
// cout<<ans<<endl;
return ans;
}
int main(){
#ifdef Devil_Gary
freopen("gugu.in","r",stdin);
#endif
n=read(),m=read(),scanf("%s",s+1),fail[0]=fail[1]=1,len[1]=-1;
for(int i=1;i<=n;i++) dd[i]=extend(s[i]-'a',i);
build(),dfs(1);
for(int i=1,k;i<=m;i++) L[i]=read(),k=read(),pre[i]=h[k],h[k]=i;
for(int i=1;i<=n;i++){
int x=dd[i];
for(int j=x;j;j=fail[nxt[j]]){
/* bug(j);
bug(id);*/
Add(max(1,Query(1,1,id,in[j],out[j])-len[j]+2),1);
/* bug(j);
bug(i-len[nxt[j]]+2);*/
Add(i-len[nxt[j]]+2,-1);
}
modify(1,1,id,in[x],i);
for(int j=h[i];j;j=pre[j]) ans[j]=ask(L[j]);
}
for(int i=1;i<=m;i++) (Ans+=(ll)ans[i]*i%mod)%=mod;
printf("%d\n",Ans);
}

BZOJ5384 有趣的字符串题 回文树的更多相关文章

  1. 字符串hash+回文树——hdu6599

    拖了很久才补的回文树,感觉网上的博客都是一个做法..回文树统计不同种类的回文串出现次数,然后用字符串hash来判每个回文子串是否符合要求 #include<bits/stdc++.h> u ...

  2. Palindrome Mouse(2019年牛客多校第六场C题+回文树+树状数组)

    目录 题目链接 题意 思路 代码 题目链接 传送门 题意 问\(s\)串中所有本质不同的回文子串中有多少对回文子串满足\(a\)是\(b\)的子串. 思路 参考代码:传送门 本质不同的回文子串肯定是要 ...

  3. UVALive-7041(回文树

    题意:给你两个字符串,问你有多少对公共回文串. 思路:先对a字符串建回文树.然后再把b字符串加进去就好了. #include<cstdio> #include<cmath> # ...

  4. 2014-2015 ACM-ICPC, Asia Xian Regional Contest G The Problem to Slow Down You 回文树

    The Problem to Slow Down You Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjud ...

  5. [模板] 回文树/回文自动机 && BZOJ3676:[Apio2014]回文串

    回文树/回文自动机 放链接: 回文树或者回文自动机,及相关例题 - F.W.Nietzsche - 博客园 状态数的线性证明 并没有看懂上面的证明,所以自己脑补了一个... 引理: 每一个回文串都是字 ...

  6. UESTC - 1999 也许这是唯一能阻止乐爷AK的方法( Just for Fun )(回文树)

    https://vjudge.net/problem/UESTC-1999 题意 对于一个初始为空的字符串S,你可以进行以下两种操作: 1. 在S的末尾加一个小写字母. 2. 移除S的最后一个字母. ...

  7. BZOJ - 3676 回文串 (回文树)

    https://vjudge.net/problem/HYSBZ-3676 题意 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s ...

  8. 回文树&后缀自动机&后缀数组

    KMP,扩展KMP和Manacher就不写了,感觉没多大意思.   之前感觉后缀自动机简直可以解决一切,所以不怎么写后缀数组.   马拉车主要是通过对称中心解决问题,有的时候要通过回文串的边界解决问题 ...

  9. Gym - 101806Q:QueryreuQ(回文树)

    A string is palindrome, if the string reads the same backward and forward. For example, strings like ...

随机推荐

  1. java虚拟机内存不足,“Could not create the Java Virtual Machine”问题解决方案

    在运行java程序时,遇到问题"Could not create the Java Virtual Machine."如下截图:

  2. 用Python实现Excel的读写

    一.读excel文件的简单示例 #!/usr/bin/env python # -*- coding:utf-8 -*- import xlrd from xlrd.book import Book ...

  3. [转]Hadoop参数汇总

    出自:https://segmentfault.com/a/1190000000709725 Hadoop参数大全 主要配置文件: core hdfs yarn mapred 重要性表示如下: 重要 ...

  4. 用PNChart绘制饼状图简介

    写在前面 最近做的小Demo中有一个绘制饼状图的需求.在开始实现之前上网了解了一下现有的一些绘制图形的第三方库,相应的库还是有挺多的,PNChart便是其中一个.PNChart是一个90后的中国boy ...

  5. 【转】crontab实用手册

    前言 crontab是Unix和Linux用于设置周期性被执行的指令,是互联网很常用的技术,很多任务都会设置在crontab循环执行,如果不使用crontab,那么任务就是常驻程序,这对你的程序要求比 ...

  6. DFMZ-开发过程中遇到的错误-01

    未能加载文件或程序集“H2F, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”或它的某一个依赖项.试图加载格式不正确的程序. 原因分析:由 ...

  7. 一.hadoop入门须知

    目录: 1.hadoop入门须知 2.hadoop环境搭建 3.hadoop mapreduce之WordCount例子 4.idea本地调试hadoop程序 5.hadoop 从mysql中读取数据 ...

  8. 解决Oracle出现以0开头的小数,开头的0消失的问题

    项目中碰到了个问题,本来报表需要显示“0.49%”,结果就是显示成“.49%” 找问题 首先在pl/sql工具里执行sql,发现原始的数据就是“.49%”,那么问题来了,原始sql的问题,跟工具无关了 ...

  9. 《转》Pragma: no-cache 对性能的影响

    做了下go和java的http性能的简单比较服务端直接输出字符串使用JMeterwindows下  2000的并发,测试结果很出乎意料,go不会这么差吧 研究了半小时,原因如下tomcat的servl ...

  10. HDU 2594 最长相同前后缀

    Sample Inputclintonhomerriemannmarjorie Sample Output0rie 3 输入两个字符串 ,求最长相同前后缀直接把两个字符串连接在一起求next就行了,唯 ...