zoukankan      html  css  js  c++  java
  • loj#3055. 「HNOI2019」JOJO

    题目描述


    题解

    并没有注意到相邻串字母不同,x=1想到用辅助数组加速跳next

    首先显然离线,对每一段末尾求next,next的定义修改为匹配到的位置一定所在串的末尾

    第一段长度大于等于,其他段长度刚好等于,把每一段当作特殊字符来做kmp,在找的时候算答案,答案是若干等差数列之和

    由于kmp时间均摊,所以直接跳会被卡,因此如果长度大于一半的话就判断然后跳到周期等差数列的开头,时间是log的

    总时间为O(nlog|S|)

    code

    实际上暴力跳也可以

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define min(a,b) (a<b?a:b)
    #define mod 998244353
    #define ll long long
    #define file
    using namespace std;
    
    int a[100011][2],A[100011][2],ls[100011],d[100011][2],id[100011],nx[100011],n,i,j,k,l,len,tot,tp;
    ll ans,Len[100011],Ans[100001];
    vector<int> b[100011];
    char ch;
    
    void New(int x,int y,int s1,int s2) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;A[len][0]=s1,A[len][1]=s2;}
    void dfs(int t,ll ans)
    {
    	ll ANS=ans;
    	int i;
    	
    	j=b[t].size();
    	fo(i,0,j-1)
    	Ans[b[t][i]]=ans;
    	
    	for (i=ls[t]; i; i=a[i][1])
    	{
    		++tot;d[tot][0]=A[i][0],d[tot][1]=A[i][1];Len[tot]=Len[tot-1]+A[i][1];
    		
    		if (tot==1) nx[tot]=0,ans=(1ll*A[i][1]*(A[i][1]-1)/2)%mod;
    		else
    		{
    			nx[tot]=nx[tot-1];l=0;
    			while (nx[tot] && !(d[nx[tot]+1][0]==d[tot][0] && d[nx[tot]+1][1]==d[tot][1]))
    			{
    				if (d[nx[tot]+1][0]==d[tot][0] && d[nx[tot]+1][1]>l)
    				{
    					k=min(d[nx[tot]+1][1],A[i][1]);
    					ans=(ans+Len[nx[tot]]*(k-l)%mod+(1ll*(l+1+k)*(k-l)/2)%mod)%mod;
    					l=k;
    				}
    				
    				if (Len[nx[nx[tot]]]>Len[nx[tot]]/2)
    				{
    					if (!(d[nx[nx[tot]]+1][0]==d[tot][0] && (d[nx[nx[tot]]+1][1]>l || d[nx[nx[tot]]+1][1]==d[tot][1])))
    					nx[tot]-=((Len[nx[tot]]-(Len[nx[tot]]/2+1))/(Len[nx[tot]]-Len[nx[nx[tot]]]))*(nx[tot]-nx[nx[tot]]);
    				}
    				nx[tot]=nx[nx[tot]];
    			}
    			k=min(d[nx[tot]+1][1],A[i][1]);
    			if (d[nx[tot]+1][0]==d[tot][0])
    			{
    				ans=(ans+Len[nx[tot]]*(k-l)%mod+(1ll*(l+1+k)*(k-l)/2)%mod)%mod;
    				l=k;
    				ans=(ans+Len[1]*(A[i][1]-k))%mod;
    			}
    			
    			nx[tot]+=(d[nx[tot]+1][0]==d[tot][0] && d[nx[tot]+1][1]<=d[tot][1]);
    		}
    		
    		dfs(a[i][0],ans);
    		ans=ANS,--tot;
    	}
    }
    
    int main()
    {
    //	#ifdef file
    //	freopen("jojo6.in","r",stdin);
    //	#endif
    //	freopen("b.out","w",stdout);
    	
    	scanf("%d",&n);
    	l=tot=1;id[0]=1;
    	fo(i,1,n)
    	{
    		scanf("%d",&tp);
    		if (tp==1)
    		{
    			scanf("%d%c%c",&j,&ch,&ch);
    			++tot;
    			New(l,tot,ch-'a'+1,j);
    			l=tot;
    		}
    		else
    		{
    			scanf("%d",&j);
    			l=id[j];
    		}
    		b[l].push_back(i);id[i]=l;
    	}
    	
    	tot=0;
    	dfs(1,0);
    	fo(i,1,n) printf("%lld
    ",Ans[i]);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    自定义Web框架
    Python四种实现单例模式的方法
    popup的简单应用举例
    前端框架之BootStrap的简单介绍
    前端之JQuery:JQuery扩展和事件
    前端之JQuery:JQuery文档操作
    前端之JQuery:JQuery属性操作
    前端之JQuery:JQuery基本语法
    MinerDB.java 数据库工具类
    MinerConstanits.java 常量类
  • 原文地址:https://www.cnblogs.com/gmh77/p/13284842.html
Copyright © 2011-2022 走看看