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;
    }
    
  • 相关阅读:
    两年工作感想
    ASP常用的38个内置函数
    asp汉字转换成汉语拼音
    js高级表格排序
    使用XmlHttpRequest对象调用Web Services 服务
    75个最佳Web设计资源
    C# FTP操作类
    存储过程操作类
    Windows Mobile 5.0 SDK 下载地址
    链表C#实现
  • 原文地址:https://www.cnblogs.com/colazcy/p/13615836.html
Copyright © 2011-2022 走看看