SPOJ NSUBSTR

Problem : 给一个长度为n的字符串,要求分别输出长度为1~n的子串的最多出现次数。

Solution :首先对字符串建立后缀自动机,在根据fail指针建立出后缀树,对于n个后缀对应的节点打上标记,则每个结点对应的一些子串所出现的次数即为其子树内标记的个数,在后缀树上进行1遍dfs统计,之后根据答案的单调性线性扫描一遍进行统计。

#include <iostream>
#include <string>
#include <cstring>
using namespace std; const int N = 250008; struct node
{
int u, v, nt;
}; struct Suffix_Automaton
{
int nt[N << 1][26], a[N << 1], fail[N << 1];
int tot, last, root;
int p, q, np, nq; int lt[N << 1], sum;
node eg[N << 2];
int dp[N << 1], cnt[N << 1]; void add(int u, int v)
{
eg[++sum] = (node){u, v, lt[u]}; lt[u] = sum;
eg[++sum] = (node){v, u, lt[v]}; lt[v] = sum;
}
int newnode(int len)
{
for (int i = 0; i < 26; ++i) nt[tot][i] = -1;
fail[tot] = -1; a[tot] = len;
return tot++;
}
void clear()
{
memset(lt, 0, sizeof(lt));
tot = last = 0; sum = 0;
root = newnode(0);
}
void insert(int ch)
{
p = last; last = np = newnode(a[p] + 1); cnt[np] = 1;
for (; ~p && nt[p][ch] == -1; p = fail[p]) nt[p][ch] = np;
if (p == -1) fail[np] = root;
else
{
q = nt[p][ch];
if (a[p] + 1 == a[q]) fail[np] = q;
else
{
nq = newnode(a[p] + 1);
for (int i = 0; i < 26; ++i) nt[nq][i] = nt[q][i];
fail[nq] = fail[q];
fail[np] = fail[q] = nq;
for (; ~p && nt[p][ch] == q; p = fail[p]) nt[p][ch] = nq;
}
}
}
void dfs(int u, int fa)
{
for (int i = lt[u]; i; i = eg[i].nt)
{
int v = eg[i].v;
if (v != fa)
{
dfs(v, u);
cnt[u] += cnt[v];
}
}
dp[a[u]] = max(dp[a[u]], cnt[u]);
}
void solve(int len)
{
for (int i = 1; i < tot; ++i) add(fail[i], i);
dfs(root, -1);
for (int i = len - 1; i >= 1; i--) dp[i] = max(dp[i], dp[i + 1]);
for (int i = 1; i <= len; ++i) printf("%d\n", dp[i]);
}
}sam; int main()
{
cin.sync_with_stdio(0);
sam.clear();
string s; cin >> s;
for (int i = 0, len = s.length(); i < len; ++i)
sam.insert(s[i] - 'a');
sam.solve(s.length());
}

SPOJ NSUBSTR (后缀自动机)的更多相关文章

  1. SPOJ - NSUBSTR 后缀自动机板子

    SPOJ - NSUBSTR #include<bits/stdc++.h> #define LL long long #define fi first #define se second ...

  2. 长度为x的本质不同的串的出现次数 SPOJ - NSUBSTR 后缀自动机简单应用

    题意: 长度为x的本质不同的串的出现次数 题解: 先处理出每一个节点所对应的子串出现的次数 然后取max就好了 #include <set> #include <map> #i ...

  3. SPOJ LCS 后缀自动机

    用后缀自动机求两个长串的最长公共子串,效果拔群.多样例的时候memset要去掉. 解题思路就是跟CLJ的一模一样啦. #pragma warning(disable:4996) #include< ...

  4. SPOJ - LCS 后缀自动机入门

    LCS - Longest Common Substring A string is finite sequence of characters over a non-empty finite set ...

  5. SPOJ LCS 后缀自动机找最大公共子串

    这里用第一个字符串构建完成后缀自动机以后 不断用第二个字符串从左往右沿着后缀自动机往前走,如能找到,那么当前匹配配数加1 如果找不到,那么就不断沿着后缀树不断往前找到所能匹配到当前字符的最大长度,然后 ...

  6. SPOJ 7258 (后缀自动机)

    转载:http://hzwer.com/4492.html 给一个长度不超过90000的串S,每次询问它的所有不同子串中,字典序第K小的,询问不超过500个. 搞出后缀自动机 dp处理出每个点往下走能 ...

  7. 多个串的最长公共子串 SPOJ - LCS2 后缀自动机

    题意: 求多个串的最长公共子串 这里用的是O(n)的后缀自动机写法 我后缀数组的专题有nlog(n)写法的 题解: 对于其中的一个串建立后缀自动机 然后对于后缀自动机上面的每一个节点求出每一个节点最长 ...

  8. Spoj REPEATS 后缀自动机+set

    REPEATS - Repeats 链接:http://www.spoj.com/problems/REPEATS 题意:求S串中某个子串连续循环次数最多的次数. 想法: 从暴力开始,枚举所有串,求出 ...

  9. SPOJ - SUBLEX 后缀自动机

    SPOJ - SUBLEX 思路:求第k大字串,求出sam上每个节点开始能识别多少字串,然后从起点开始跑就好啦. #include<bits/stdc++.h> #define LL lo ...

随机推荐

  1. andorid IOS 判断APP下载

    <?phpif(strpos($_SERVER['HTTP_USER_AGENT'], 'iPhone')||strpos($_SERVER['HTTP_USER_AGENT'], 'iPad' ...

  2. 技术杂记之:vi使用入门

    对于Linux的初次使用者来说,进入Linux非图形界面后,不知道怎么创建文本(甚至于在图形界面,也找不到创建文本的菜单).其实,每一个Linux的发行版本,都包含了一个最简单.也是最基础的文本编辑器 ...

  3. Mac OS 下安装和配置 maven

    1. 安装 Maven 前的必须准备 需先安装 Java 环境 下载合适的 JDK 配置 JDK 环境变量 JAVA_HOME:为 JDK 安装目录 Path:为 JDK/bin 目录 测试是否成功: ...

  4. APK瘦身-是时候给App进行减负了

    前言 APK瘦身即是对APK大小进行压缩策略,减小APK安装包大小,更小的安装包更有助于吸引用户安装.前一段时间我司某一App进行APK的瘦身,最终也达到了减小10M的目标,现做一个简单的总结记录. ...

  5. iOS Programming Camera 1

     iOS Programming Camera  1 1 Displaying Images and UIImageView 1.1  put an instance of UIImageView o ...

  6. cal - 显示一个日历

    总览 cal [-mjy ] [月份 [年份 ] ] 描述 Cal 显示一个简单的日历.. 如果没有指定参数, 则显示当前月份. 选项如下所列: -m 显示星期一作为一周的第一天.. (缺省为星期日. ...

  7. 在DOS行下设置静态IP

    A.设置静态IP  CMD  netsh  netsh>int  interface>ip  interface ip>set add "本地链接" static ...

  8. https://quotefancy.com/ 经典句子(英语) 真是特别好~

    https://quotefancy.com/ 经典句子(英语)

  9. 纯CSS3来自定义单选框radio与复选框checkbox

    单选框(radio)自定义样式 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 3 ...

  10. CAD参数绘制直线(网页版)

    用户可以在CAD控件视区任意位置绘制直线. 主要用到函数说明: _DMxDrawX::DrawLine 绘制一个直线.详细说明如下: 参数 说明 DOUBLE dX1 直线的开始点x坐标 DOUBLE ...