zoukankan      html  css  js  c++  java
  • BZOJ5384 有趣的字符串题 回文树

    神奇的结论:

    一个字符串的所有回文后缀的长度,可以形成(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
    ",Ans);
    }
    
    
    
  • 相关阅读:
    LR 两种录制:html与url
    性能测试心得之一
    杂记
    基于 python 的接口测试框架
    POJ3579 Median
    洛谷P4035 [JSOI2008]球形空间产生器
    洛谷P2455 [SDOI2006]线性方程组
    POJ2393 Yogurt factory
    洛谷P3763 [TJOI2017]DNA
    洛谷P2234 [HNOI2002]营业额统计
  • 原文地址:https://www.cnblogs.com/devil-gary/p/9244481.html
Copyright © 2011-2022 走看看