zoukankan      html  css  js  c++  java
  • 题解 P3435【[POI2006]OKR-Periods of Words】

    题目链接

    Solution [POI2006]OKR-Periods of Words

    题目大意:给定一个字符串,求出对于所有前缀的最大周期长度之和。

    KMP


    分析:可以考虑这题在(fail)树上的性质

    比较显然,一个前缀的最大周期长度,就等于前缀本身的长度减去最小非空(border)的长度

    我们将(fail)树建出来,将虚拟(0)号点作为根,问题即为:对于每个节点,尽可能往上跳,不能到(0)点,到达点的编号之和(每个点代表一个前缀,点的编号即为前缀长度)

    直接做复杂度爆炸,我们可以枚举(0)号点的每一个儿子,将它的编号乘以它的子树大小

    复杂度就可以做到(O(n))

    #include <cstdio>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e6 + 100;
    char str[maxn];
    int n,pi[maxn],siz[maxn];
    vector<int> G[maxn];
    ll ans;
    inline void addedge(int from,int to){G[from].push_back(to);}
    inline void dfs(int u){
    	siz[u] = 1;
    	for(int v : G[u])dfs(v),siz[u] += siz[v];
    	if(u == 0){
    		for(int v : G[u])ans -= 1ll * v * siz[v];
    	}
    }
    int main(){
    	scanf("%d",&n);
    	scanf("%s",str + 1);
    	for(int i = 2;i <= n;i++){
    		int j = pi[i - 1];
    		while(j > 0 && str[j + 1] != str[i])j = pi[j];
    		if(str[j + 1] == str[i])j++;
    		pi[i] = j;
    	}
    	for(int i = 1;i <= n;i++)addedge(pi[i],i);
    	ans = (1ll * n * (n + 1)) >> 1;
    	dfs(0);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Idea14 生成webservices
    第10组 Beta冲刺(4/4)
    2019 SDN上机第7次作业
    第10组 Beta冲刺(3/4)
    第10组 Beta冲刺(2/4)
    第10组 Beta冲刺(1/4)
    2019 SDN上机第6次作业
    SDN课程阅读作业(2)
    2019 SDN上机第5次作业
    第10组 Alpha冲刺(4/4)
  • 原文地址:https://www.cnblogs.com/colazcy/p/13615836.html
Copyright © 2011-2022 走看看