SPOJ8222/NSUBSTR:Substrings——题解

https://www.luogu.org/problemnew/show/SP8222#sub

http://www.spoj.com/problems/NSUBSTR/

翻译来自洛谷。

你得到一个字符串,最多由25万个小写拉丁字母组成。我们将 F(x)定义为某些长度X的字符串在s中出现的最大次数,例如字符串‘ababaf‘- F(x),因为有一个字符串‘ABA‘出现两次。你的任务是输出 F(x)每一个I,以使1<=i<=|S|.

water!

后缀自动机后对l排个序,对每个l更新其ans就做完了。

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
typedef long long ll;
const int N=500005;
struct tree{
    int a[26],fa,l;
}tr[N];
char s[N];
int last,cnt,ans[N];
int a[N],w[N],size[N];
inline void insert(int c){
    int p=last,np=++cnt;
    last=np;tr[np].l=tr[p].l+1;
    for(;p&&!tr[p].a[c];p=tr[p].fa)tr[p].a[c]=np;
    if(!p)tr[np].fa=1;
    else{
    int q=tr[p].a[c];
    if(tr[p].l+1==tr[q].l)tr[np].fa=q;
    else{
        int nq=++cnt;tr[nq].l=tr[p].l+1;
        memcpy(tr[nq].a,tr[q].a,sizeof(tr[q].a));
        tr[nq].fa=tr[q].fa;tr[q].fa=tr[np].fa=nq;
        for(;p&&tr[p].a[c]==q;p=tr[p].fa)tr[p].a[c]=nq;
    }
    }
    size[np]=1;
}
int main(){
    scanf("%s",s);
    int len=strlen(s);
    last=cnt=1;
    for(int i=0;i<len;i++)insert(s[i]-‘a‘);
    for(int i=1;i<=cnt;i++)w[tr[i].l]++;
    for(int i=1;i<=len;i++)w[i]+=w[i-1];
    for(int i=1;i<=cnt;i++)a[w[tr[i].l]--]=i;
    for(int i=cnt;i>=1;i--){
    size[tr[a[i]].fa]+=size[a[i]];
    ans[tr[a[i]].l]=max(ans[tr[a[i]].l],size[a[i]]);
    }
    for(int i=1;i<=len;i++)printf("%d\n",ans[i]);
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

原文地址:https://www.cnblogs.com/luyouqi233/p/8776312.html

时间: 2024-11-10 13:27:22

SPOJ8222/NSUBSTR:Substrings——题解的相关文章

[SPOJ8222]NSUBSTR - Substrings 后缀自动机

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int sz=0,la,rt; 6 int ch[500010][26],l[500010],fa[500010]; 7 void Extend(int c){ 8 int end=++sz,tmp=la; 9 l[end]=l[tmp]+1; 10 while(tmp&&!ch[tm

SPOJ8222 NSUBSTR - Substrings 后缀自动机_动态规划

讲起来不是特别好讲.总之,如果 $dp[i+1]>=dp[i]$,故$dp[i]=max(dp[i],dp[i+1])$ Code: #include <cstdio> #include <algorithm> #include <cstring> #define setIO(s) freopen(s".in","r",stdin) #define maxn 2000000 #define N 30 #define ll l

SPOJ NSUBSTR - Substrings

NSUBSTR - Substrings no tags You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as the maximal number of times that some string with length x appears in S. For example for string 'ababa' F(3) will be 2 b

SPOJ 8222 NSUBSTR Substrings

SAM的简单应用.... 由SAM可知从root到达的每个节点所经过的路径都对着应原串的一个子串,每个节点能到几次接收态就等于这个子串出现了几次.从最后一个节点往上走,就可以用DP更新出每个子串出现了多少次. 出现了5次的子串一定也出现了4,3,2,1次...所以最后再用长度长的给长度小的更新一下.... Substrings Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [Submit]  

【spoj8222】 Substrings

http://www.spoj.com/problems/NSUBSTR/ (题目链接) 题意 给出一个字符串S,令${F(x)}$表示S的所有长度为x的子串出现次数的最大值.求${F(1)......F(length(S))}$ Solution 后缀自动机例题,下面写几点自己认为理解后缀自动机的重点. 后缀自动机相对于后缀树就是将Right集合相同的子串合用一个节点来表示.每一个节点代表一个状态S,这个状态可能包含很多长度区间连续的子串,这些子串的右端点固定,它们的Right集合相同. 往上

●SPOJ 8222 NSUBSTR - Substrings

题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 后缀自动机的水好深啊!懂不了相关证明,带着结论把这个题做了.看来这滩深水要以后再来了. 本题要用到一个叫 Right[P] 的数组,表示 P对应的子串在原串中出现的所有位置的末尾位置下标的集合.本题中,用这个数组存储集合大小就好了,即 P对应的子串在原串中出现了Right[p]次. 而Right[P]的值,等于从改点出发到结束状态的方案数.但这个不好求,而是要用到另一个求法:用 Parent树: (暂时由

【spoj8222】Substrings

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #define maxn 500005 7 #define maxm 250005 8 using namespace std; 9 10 int n,tot,root,last,f[maxm],fa[maxn],son[maxn][2

并不对劲的[spoj nsubstr]substrings

题意是求一个字符串每个长度的子串出现次数最多的那个出现了多少次,也就是求每个到根的最长路的right集合最大值 . 先建后缀自动机,然后将每个前缀所在的集合的初值设为1,因为所有前缀的right集合肯定不相同,而且它们包含了所有位置. 接下来按到根的最长距离从大到小排序,将right集合累加到parent上.这么排序是因为到根的最长距离长的状态肯定不是到根的最长距离短的状态的parent. 最后直接求到根的不同的最长距离的最大的right集合就行. #include<iostream> #in

POJ3415:Common Substrings——题解

http://poj.org/problem?id=3415 给定两个字符串A 和B,求长度不小于k 的公共子串的个数(可以相同). 论文题,和上道题(POJ2774)类似,首先想到现将AB串合并,然后子串可以表示成字符串后缀的前缀,于是我们比较任意两个A后缀和B后缀,用height求出他们的公共子串长度就很好做了. (不懂为什么好做的可以看SPOJ694) 那么最坏的想法就是每遇到B后缀就和前面遇到的A后缀比较,这样显然TLE,也没用到height数组的优越性. 但是我们A后缀可以用单调栈维护