zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    DataGridView 密码列(显示为*号)的设置
    有關界面化學的一些有趣現象
    电商网站需要ICP证吗
    JS 未结束的字符串常量
    Iframe自适应高度
    JS正则表达式
    界面活性劑的作用
    js转义字符
    解决dbo登录名为空的问题
    肌肤弹性胶原蛋白
  • 原文地址:https://www.cnblogs.com/zzctommy/p/13889081.html
Copyright © 2011-2022 走看看