【hihocoder】sam-3

把Parent Tree拓扑排序下,然后从下往上合并。

具体的看官方题解啦~

#include<bits/stdc++.h>
#define N 1000010
using namespace std;
int n;char s[N];
int tot=0,head[N<<1];
struct Edge{int u,v,next;}G[N<<1];
int size[N<<1],ans[N];
struct Suffix_Automaton{
    int fa[N<<1],ch[N<<1][30],l[N<<1],r[N<<1],rt,cnt,last;
    Suffix_Automaton(){cnt=last=1;rt=1;}
    void ins(int c){
        int p=last,np=++cnt;last=np;l[np]=l[p]+1;
        for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
        if(!p){fa[np]=rt;r[np]=1;}
        else{
            int q=ch[p][c];
            if(l[p]+1==l[q]){fa[np]=q;r[np]=l[q]+1;}
            else{
                int nq=++cnt;l[nq]=l[p]+1;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q];r[nq]=l[fa[q]]+1;
                fa[q]=fa[np]=nq;r[q]=r[np]=l[nq]+1;
                for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;
            }
        }
    }
}sam;
inline void addedge(int u,int v){
    G[++tot].u=u;G[tot].v=v;G[tot].next=head[u];head[u]=tot;
}
void dfs(int u){
    for(int i=head[u];i;i=G[i].next){
        int v=G[i].v;dfs(v);
        size[u]+=size[v];
    }
    if(!head[u])size[u]=1;
}
int main(){
    scanf("%s",s+1);n=strlen(s+1);
    sam.ins(0);
    for(int i=1;i<=n;i++)sam.ins(s[i]-‘a‘+1);
    for(int i=2;i<=sam.cnt;i++)addedge(sam.fa[i],i);dfs(1);
    for(int i=2;i<=sam.cnt;i++)ans[sam.l[i]]=max(ans[sam.l[i]],size[i]);
    for(int i=n-1;i;i--)ans[i]=max(ans[i],ans[i+1]);
    for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
}
时间: 2024-10-09 01:50:45

【hihocoder】sam-3的相关文章

【hihoCoder】回文字符序列

描述 给定字符串,求它的回文子序列个数.回文子序列反转字符顺序后仍然与原序列相同.例如字符串aba中,回文子序列为"a", "a", "aa", "b", "aba",共5个.内容相同位置不同的子序列算不同的子序列. 输入 第一行一个整数T,表示数据组数.之后是T组数据,每组数据为一行字符串. 输出 对于每组数据输出一行,格式为"Case #X: Y",X代表数据编号(从1开始),Y为答

【hihoCoder】基站选址

时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 需要在一个N × M的网格中建立一个通讯基站,通讯基站仅必须建立在格点上. 网格中有A个用户,每个用户的通讯代价是用户到基站欧几里得距离的平方. 网格中还有B个通讯公司,维护基站的代价是基站到最近的一个通讯公司的路程(路程定义为曼哈顿距离). 在网格中建立基站的总代价是用户通讯代价的总和加上维护基站的代价,最小总代价. 输入 第一行为一个整数T,表示数据组数. 每组数据第一行为四个整数:N, M, A, B. 接下来的A

【hihoCoder】1082: 然而沼跃鱼早就看穿了一切

  题目:http://hihocoder.com/problemset/problem/1082 输入一个字符串,将其中特定的单词替换成另一个单词   代码注意点: 1. getline(istream &in, string &s) 没有读入字符,将返回false 2. transform(tmp.begin(),tmp.end(),tmp.begin(),::tolower) 将tmp的所有字母都改成小写 需要包含 #include <algorithm> 3. 查找函数

【hihoCoder】1033: 交错和

初探数位dp 介绍了数位类统计的基础知识.以下列出其中的基础点: 基本问题 统计在区间[l, r]中满足条件的数的个数 思路 1. [l, r] 将问题转换为 在[0, r]中满足条件的个数 - 在[0, l)满足条件的个数 2. 求解 区间[0, n]满足条件的个数 性质:一个小于n的数m,一定是从高位到低位在某一位小于n的对应位的一个数   数值 百位 十位 个位   n 358 3 5 8   m 350 3 5 0 0<8 m 349 3 4 9 4<5 遍历所有小于n的数:从高位到低

【hihoCoder】1036 Trie图

题目:http://hihocoder.com/problemset/problem/1036 给一个词典dict,词典中包含了一些单词words.要求判断给定的一个文本串text中是否包含这个字典中的单词words. 相关基础的理解 1. 与用KMP解决的问题的差别 KMP:输入原串S和一个模式串T,判断T是否出现在S中.通过对T计算next数组,避免原串S的回溯. 现在的问题:输入文本串text和多个单词words,判断words中是否有出现在text中.同样希望输入的text不用进行回溯.

【hihocoder】sam1-基本概念

这题有毒-- 原本只是想复习下sam,于是写-- 后来发现自己傻了不知道怎么维护endpos-- 一气之下直接kmp拉倒,mdzz UPD:现在我好像会维护endpos了-- #include<bits/stdc++.h> #define N 100010 using namespace std; int a[N],l,n,b[N],t,nxt[N]; struct Suffix_AutoMaton{ int cnt,last,ch[N][26],l[N],r[N],fa[N]; void i

【hihoCoder】【挑战赛#12】

模拟+枚举+模拟……+构造 QAQAQQQ rank12求杯子! A 顺子 ……模拟题,分类讨论一下就好了……比如当前四张牌是不是同一花色……是不是连续的四张牌,如果是连续的四张牌,是不是两边的……(呀我好像忘了判左边...只判了J Q K A....没判A 2 3 4... 没关系加几个字符就好了……嗯代码已改 1 //hihocoder 12 A 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5

【Hihocoder】1014 : Trie树

问题:http://hihocoder.com/problemset/problem/1014 给定一个字符串字典dict,输入字符串str, 要求从dict中找出所有以str为前缀的字符串个数. 构建Trie树: 1) 一个节点有多个子节点.用vector<Node*> nexts 存储. 2) 两个字符串的相同前缀部分共用同一条路径. 3) 每个节点包含计数变量 cnt, 表示有多少个字符串共用该节点 复杂度分析: 假定dict中的字符串个数 n, 字符串的长度 l 1)建树:O(n^2*

【hihoCoder】1037 : 数字三角形

题目:http://hihocoder.com/problemset/problem/1037 一个迷宫有n层,第i层有i个房间 从第i层的第i个房间(i, i)可以走到第i+1层的第i个房间或第i+1房间(i+1, i)/(i+1, i+1) 每个房间走出去后都不能回头 样例输入 5 //迷宫的层数 2 6 4 1 2 8 4 0 9 6 6 5 5 3 6思路动态规划maze[i, j] = max(maze[i-1, j], maze[i-1, j-1]) 源码 1 #include <i