• P3435 [POI2006]OKR-Periods of Words


    P3435 [POI2006]OKR-Periods of Words

    卡了好久,一直不敢确认思路是对的。。。

    这题非常显然可以转化成“对于每一个 (S_{1,cdots,i}) 求出最短公共前后缀 (q_j)”,那么 (ans=sum i-q_i)

    首先求出 (KMP)(next) 数组,那么最短公共前后缀就是在 (next) 不为 (-1) 的情况下不断跳。

    每次暴力跳的复杂度是不对的,实测 TLE 74

    考虑类似并查集的路径压缩进行优化因为中间经过的路径能压缩就压缩,不影响答案(当然也可以连边 (next_i o i) ,跑DAG)

    均摊一下复杂度还是 (O(n))

    另外,教练说字符串下标从零开始是一种信仰,于是我就改了。。。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef double db;
    #define x first
    #define y second
    #define sz(v) (int)v.size()
    #define pb(x) push_back(x)
    #define mkp(x,y) make_pair(x,y)
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=0;c=getchar();}
    	while(isdigit(c))x=x*10+c-'0',c=getchar();
    	return f?x:-x;
    }
    #define N 1000005
    int n,P[N];
    char str[N];
    LL ans;
    signed main(){
    	scanf("%d%s",&n,str);
    	int j=-1;P[0]=-1;
    	for(int i=1;i<n;++i){
    		while(~j&&str[j+1]!=str[i])j=P[j];
    		if(str[j+1]==str[i])++j;
    		P[i]=j;
    	}
    	for(int i=0;i<n;++i){
    		j=P[i];
    		while(~j&&~P[j])P[i]=j=P[j];
    		if(~j)ans+=i-j;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    使用Docker及k8s启动logstash服务
    在kubernetes上部署zookeeper,kafka集群
    k8s configmap 挂载配置文件
    k8s 安装 rabbitMQ 单机版
    aws 挂载efs (nfs)目录
    长白山游记
    RedHat 安装YUM软件
    mysql查询案例
    mysql子查询
    mysql联合查询
  • 原文地址:https://www.cnblogs.com/zzctommy/p/13889081.html
Copyright © 2020-2023  润新知