http://acm.hdu.edu.cn/showproblem.php?pid=4641

http://acm.hdu.edu.cn/showproblem.php?pid=6194

题意: 开始时给出一个字符串,给出两种操作,一种是在字符串后面添加一个字符,
另一个是查询出现过最少出现K次的字串个数。

分析:

建立后缀自动机,添加一个字符插入即可,对于查询,前面计算过的没必要再算,
直接从当前开始往前面找,已经达到K次的就不管,说明前面已经计算过,现在达到
K次的加进答案。

#include<bits/stdc++.h>
using namespace std;
#define mem(a , b) memset(a , b , sizeof(a))
const int maxn = ;
#define ll long long struct SAM{
int trans[maxn<<][] , slink[maxn<<] , maxlen[maxn<<];
int last , now , root;
ll ans=;
int sum[maxn<<];
void newnode(int v)
{
maxlen[++now]=v;
mem(trans[now],); }
void extend(int c , int k)
{
newnode(maxlen[last] + );
int p = last , np = now;sum[now]=;
// cout<<now<<endl;
while(p && !trans[p][c])
{
trans[p][c] = np;
p = slink[p];
}
if(!p) slink[np] = root;
else
{
int q = trans[p][c];
if(maxlen[p] + != maxlen[q])
{
newnode(maxlen[p] + );
int nq = now;
memcpy(trans[nq] , trans[q] , sizeof(trans[q]));
sum[nq]=sum[q];///分开的节点要继承
slink[nq] = slink[q];
slink[q] = slink[np] = nq;
while(p && trans[p][c] == q)
{
trans[p][c] = nq;
p = slink[p];
}
}
else
{
slink[np]=q;
}
}
last = np;
int w=np;
while(w && sum[w] < k )
{
sum[w]++;
if(sum[w]==k) ans+=maxlen[w]-maxlen[slink[w]];
w=slink[w];
}
// cout<<np<<endl;
}
void init()
{
root = last = now = ;
slink[root]=;
mem(trans[root],);
sum[root]=;
ans=;
} }sam;
int main()
{ int n,q,k;
while(scanf("%d%d%d",&n,&q,&k)!=EOF){
sam.init();
char str[maxn];scanf("%s",str);
for(int i= ; i<n ; i++)
{
sam.extend(str[i]-'a' , k);
}
while(q--)
{
int T;scanf("%d",&T);
getchar(); if(T==)
{ char op;
op=getchar();
sam.extend(op-'a' , k );
// cout<<op<<endl;
}
else
{
printf("%lld\n",sam.ans);
}
}
} }

关于恰好出现k次的字符串 , 我们只要求出至少k次的字串 - 至少(k+1)次的字串 ,不恰好就是k次吗

#include<bits/stdc++.h>
using namespace std;
#define mem(a , b) memset(a , b , sizeof(a))
const int maxn = ;
#define ll long long struct SAM{
int trans[maxn<<][] , slink[maxn<<] , maxlen[maxn<<];
int last , now , root;
ll ans=;
int sum[maxn<<];
void newnode(int v)
{
maxlen[++now]=v;
mem(trans[now],); }
void extend(int c , int k)
{
newnode(maxlen[last] + );
int p = last , np = now;sum[now]=;
// cout<<now<<endl;
while(p && !trans[p][c])
{
trans[p][c] = np;
p = slink[p];
}
if(!p) slink[np] = root;
else
{
int q = trans[p][c];
if(maxlen[p] + != maxlen[q])
{
newnode(maxlen[p] + );
int nq = now;
memcpy(trans[nq] , trans[q] , sizeof(trans[q]));
sum[nq]=sum[q];///分开的节点要继承
slink[nq] = slink[q];
slink[q] = slink[np] = nq;
while(p && trans[p][c] == q)
{
trans[p][c] = nq;
p = slink[p];
}
}
else
{
slink[np]=q;
}
}
last = np;
int w=np;
while(w && sum[w] < k )
{
sum[w]++;
if(sum[w]==k) ans+=maxlen[w]-maxlen[slink[w]];
w=slink[w];
}
// cout<<np<<endl;
}
void init()
{
root = last = now = ;
slink[root]=;
mem(trans[root],);
sum[root]=;
ans=;
} }sam;
int main()
{ int n,q,k;
int t;scanf("%d",&t);
while(t--)
{ string str;int k;
cin>>k>>str;
sam.init();
n=str.size();
for(int i= ; i<n ; i++)
{
sam.extend(str[i]-'a' , k);
}
ll sum1=sam.ans;
sam.init();
for(int i= ; i<n ; i++)
{
sam.extend(str[i]-'a' , k+);
}
ll sum2=sam.ans;
printf("%lld\n",sum1-sum2);
} }

HDU4641 || 6194多校 (后缀自动机-最少出现K次的字串个数 || 恰好出现K次字符串的个数)的更多相关文章

  1. SPOJ 1811 Longest Common Substring (后缀自动机第一题,求两个串的最长公共子串)

    题目大意: 给出两个长度小于等于25W的字符串,求它们的最长公共子串. 题目链接:http://www.spoj.com/problems/LCS/ 算法讨论: 二分+哈希, 后缀数组, 后缀自动机. ...

  2. CodeForces-427D:Match & Catch (后缀自动机)

    Police headquarter is monitoring signal on different frequency levels. They have got two suspiciousl ...

  3. 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数

    目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...

  4. 【算法】后缀自动机(SAM) 初探

    [自动机] 有限状态自动机的功能是识别字符串,自动机A能识别字符串S,就记为$A(S)$=true,否则$A(S)$=false. 自动机由$alpha$(字符集),$state$(状态集合),$in ...

  5. 一文读懂后缀自动机 Suffix_Automata

    原论文(俄文)地址:suffix_automata 原翻译(中文)地址:后缀自动机详解(DZYO的博客) Upd:强推浅显易懂(?)的SAM讲解 后缀自动机 后缀自动机(单词的有向无环图)--是一种强 ...

  6. 『后缀自动机入门 SuffixAutomaton』

    本文的图片材料多数来自\(\mathrm{hihocoder}\)中详尽的\(SAM\)介绍,文字总结为原创内容. 确定性有限状态自动机 DFA 首先我们要定义确定性有限状态自动机\(\mathrm{ ...

  7. Codechef2015 May - Chef and Strings (后缀自动机)

    用后缀自动机统计出出现1~n次的串的数量f[i] 对于ans[k]=sigma(f[i]*C(i,k)) i>=k ; mo=; ..maxn] of dword; nt:..maxn,'a'. ...

  8. hdu4641-K-string(后缀自动机)

    Problem Description Given a string S. K-string is the sub-string of S and it appear in the S at leas ...

  9. spoj 1812 lcsII (后缀自动机)

    spoj 1812 lcsII (后缀自动机) 题意:求多个串的lcs,最多10个串,每个串最长10w 解题思路:后缀自动机.先建好第一个串的sam,然后后面的串拿上去跑(这个过程同前一题).sam上 ...

随机推荐

  1. CTF中的变量覆盖漏洞

    https://www.cnblogs.com/bmjoker/p/9025351.html 原   作 者:bmjoker出 处:https://www.cnblogs.com/bmjoker/p/ ...

  2. BI实施的四个层次

    满足业务需求 注重数据分析汇总 统一.高效的系统集成越来越麻烦.管理人员穿梭在具有不同风格.使用逻辑的系统间,越来越厌倦,众多系统之间的业务逻辑.数据含义不一致,使用户无法判 断数据的准确性.任何一个 ...

  3. SQLServer函数 left()、charindex()、stuff()的使用

    1.left() LEFT (<character_expression>, <integer_expression>)   返回character_expression 左起 ...

  4. JMS规范简介

    一.JMS规范 Java消息服务定义: Java消息服务(Java Message Service)即JMS,是一个Java平台中面向消息中间件的API,用于在两个应用程序之间或分布式系统中发送/接受 ...

  5. WordPress 3.7.1-web截屏插件整合教程-Xproer.ScreenCapture

    插件下载(PHP):wordpress 3.7.1, 说明:由于许多插件可能使用相同钩子,导致冲突,所以提供手支方式整合. 1.上传插件目录. 说明:WordPress 3.7.1 使用的是TinyM ...

  6. 2016-2017 《移动平台开发》实验三 敏捷开发与XP实践

    概述 软件=程序+软件工程 软件企业=软件+商业模式 XP是一种轻量(敏捷).高效.低风险.柔性.可预测.科学而且充满乐趣的软件开发方式. 在更短的周期内,更早地提供具体.持续的反馈信息. 在迭代的进 ...

  7. linux数据库备份

    linux数据库备份 服务端启用二进制日志 如果日志没有启开,必须启用binlog,要重启mysql,首先,关闭mysql,打开/etc/my.cnf,加入以下几行: [mysqld] log-bin ...

  8. 解决json结合struts2时,Class org.apache.struts2.json.JSONWriter can not access a member of * 的问题

    在使用json的时候,产生的一个错误,查了一下资料,原来是struts2和json一起使用的时候,才产生的问题,虽然不影响程序的运行,但是总是会有一些异常的日志产生,并且,这个也会增加程序的负担. 原 ...

  9. Android源码设计模式分析开源项目

    简述 该项目通过分析Android系统中的设计模式来提升大家对设计模式的理解,从源码的角度来剖析既增加了对Android系统本身的了解,也从优秀 的设计中领悟模式的实际运用以及它适用的场景,避免在实际 ...

  10. JAVA 字符串编码转换

    /** * 字符串编码转换的实现方法 * @param str 待转换编码的字符串 * @param newCharset 目标编码 * @return * @throws UnsupportedEn ...