做得心 力 憔 悴

Description

你有一个字符串S,一开始为空串,要求支持两种操作
在S后面加入字母C
删除S最后一个字母
问每次操作后S有多少个两两不同的连续子串

Input

一行一个字符串Q,表示对S的操作
如果第i个字母是小写字母c,表示第一种加字母c的操作
如果为-表示删除操作,保证所有删除操作前S都非空
|Q|<=10^5

Output

输出|Q|行,第i行表示i个操作之后S内有多少个不同子串

题目分析

陈老师神题x2,暂时只会做法一。

做法一:暴力回退

还是自己菜啊……这么个暴力都写了老久。

思路就是将每一次的修改值都记录下来,再在$undo()$里回退每一个修改。说得是轻松,但是具体的实现还是要仔细安排一下顺序和细节的。

其中$stk[top]$存修改的起止点;$last[]$存每次$extend()$前的$lst$值,用于路径回退上的$ch[x][c]$修改;$tag[]$表示点$i$这次操作新增点的数量,需要分为1,2讨论回退;$val[]$表示每次操作插入的字符$c$.

有2个新增点的$undo()$稍微复杂一点,这里$stk[]={从lst回退的p';fa[q];再次回退的p'';q}$.

 #include<bits/stdc++.h>
const int maxn = ; int n,top,stk[maxn<<],last[maxn<<],tag[maxn<<],val[maxn<<];
long long ans;
struct SAM
{
int ch[maxn][],fa[maxn],len[maxn],lst,tot;
void init()
{
lst = tot = ;
}
void extend(int c)
{
int p = lst, np = ++tot;
last[++last[]] = lst;
lst = np, len[np] = len[p]+;
val[tot] = c;
for (; p&&!ch[p][c]; p=fa[p]) ch[p][c] = np;
tag[tot] = , stk[++top] = p;
if (!p) fa[np] = ;
else{
int q = ch[p][c];
if (len[p]+==len[q]) fa[np] = q;
else{
int nq = ++tot;
len[nq] = len[p]+;
tag[tot] = , val[tot] = c;
memcpy(ch[nq], ch[q], sizeof ch[q]);
stk[++top] = fa[q];
fa[nq] = fa[q], fa[q] = fa[np] = nq;
for (; p&&ch[p][c]==q; p=fa[p]) ch[p][c] = nq;
stk[++top] = p, stk[++top] = q;
}
}
ans += len[np]-len[fa[np]];
if (!tag[tot]) tag[tot] = ;
}
void undo()
{
if (tag[tot]==){
int p = last[last[]--], fnd = stk[top--], c = val[tot];
ans -= len[tot]-len[fa[tot]], lst = p;
for (; p!=fnd; p=fa[p]) ch[p][c] = ;
memset(ch[tot], , sizeof ch[tot]), --tot;
}else{
int q = stk[top--], fnd2 = stk[top--], fatq = stk[top--], fnd1 = stk[top--];
int p = last[last[]--], c = val[tot];
ans -= len[tot-]-len[fa[tot-]], lst = p;
for (; p!=fnd1; p=fa[p]) ch[p][c] = ;
fa[q] = fatq;
for (; p!=fnd2; p=fa[p]) ch[p][c] = q;
memset(ch[tot], , sizeof ch[tot]), --tot;
memset(ch[tot], , sizeof ch[tot]), --tot;
}
}
}f;
char s[maxn]; int main()
{
f.init();
scanf("%s",s+);
n = strlen(s+);
for (int i=; i<=n; i++)
{
if (s[i]=='-') f.undo();
else f.extend(s[i]-'a');
printf("%lld\n",ans);
}
return ;
}

做法二:后缀平衡树

具体的实现似乎可以用hash求LCP+multiset解决

END

【SAM】bzoj5084: hashit的更多相关文章

  1. 【SAM】codevs3160-最长公共子串

    [题目大意] 求两个字符串的最长公共子串. [思路] 对第一个字符串建立后缀自动机,第二个字符串去匹配.cnt记录当前最长公共子串的长度,而ret记录答案. p代表位置指针,初始在rt位置. 对于第二 ...

  2. 【SAM】BZOJ2882-工艺

    [题目大意] 求一个循环数列的最小表示法. [思路] 最小表示法的正解:★ SAM乱搞,和前面的POJ那道一样.然而MLE了,当作学习一下map的用法^ ^ map的使用方法(来源:☆) 一.map的 ...

  3. 【SAM】BZOJ3998-弦论

    [题目大意] 给出一个字符串,求第k大的子串.(输入1表示子串可重复,0表示不可重复) [思路] 显然,k大子串是后缀自动机的经典题型,可以利用后缀自动机的性质来解决.对于字符串 [前铺1]" ...

  4. 【SAM】POJ1509-Glass Beads

    [题目大意] 求一个循环数列的最小表示法. [思路] 把原创复制一遍放在后面,建立SAM,从s按字典序开始跑长度L即可. 板子来源(作者见连接内):

  5. 【SPOJ - LCS2】Longest Common Substring II【SAM】

    题意 求出多个串的最长公共子串. 分析 刚学SAM想做这个题的话最好先去做一下那道codevs3160.求两个串的LCS应该怎么求?把一个串s1建自动机,然后跑另一个串s2,然后找出s2每个前缀的最长 ...

  6. 【SAM】loj#6401. 字符串

    网上有篇题解写的是线段树合并维护求值? 题目描述 有一个只包含小写字母,长度为 $n$ 的字符串 $S$ .有一些字母是好的,剩下的是坏的. 定义一个子串 $S_{l\ldots r}$是好的,当且仅 ...

  7. bzoj 2946: [Poi2000]公共串【SAM】

    对第一个串建SAM,把剩下的串在上面跑,每次跑一个串的时候在SAM的端点上记录匹配到这的最大长度,然后对这些串跑的结果取min,然后从这些节点的min中取max就是答案 注意在一个点更新后它的祖先也会 ...

  8. bzoj 4698: Sdoi2008 Sandy的卡片【SAM】

    差分之后用SAM求LCS,然后答案就是LCS+1 #include<iostream> #include<cstdio> #include<cstring> usi ...

  9. bzoj 3926: [Zjoi2015]诸神眷顾的幻想乡【SAM】

    有一个显然的性质就是每个串一定在某个叶子为根的树中是一条直的链 然后因为SAM里是不会有相同状态的,所以以每个叶子为根dfs一遍,并且动态构造SAM(这里的节点u的last指向父亲),最后统计答案就是 ...

随机推荐

  1. 进击JavaScript核心 --- (1)基本数据类型

    ES5之前提供了 5种基本数据类型 和 1种引用数据类型 基本数据类型:Undefined, Null, String, Number, Boolean 引用数据类型:Object ES6开始引入了一 ...

  2. STP-11-多生成树:IEEE 802.1s

    IEEE802.1s多生成树(MultipleSpanningTrees,MST)有时也称为多STP(MultipleSTP,MSTP),它定义了在使用802.1QVLAN网络中,部署多实例STP的标 ...

  3. 一份比较完整的gulpfile.js

    var gulp = require('gulp'); //工具 var autoprefixer = require('gulp-autoprefixer'); var include = requ ...

  4. HDU-2586-How far away(LCA Tarjan离线算法)

    链接:https://vjudge.net/problem/HDU-2586 题意: 勇气小镇是一个有着n个房屋的小镇,为什么把它叫做勇气小镇呢,这个故事就要从勇气小镇成立的那天说起了,修建小镇的时候 ...

  5. Java使用comms-net jar包完成ftp文件上传进度的检测功能

    本文章只讲述大致的思路与本次功能对应的一些开发环境,具体实现请结合自己的开发情况,仅供参考,如果有不对的地方,欢迎大家指出! 准备环境:JDK1.7 OR 1.8.eclipse.ftp服务器(可自行 ...

  6. java--时间日期用法

    转载大神 https://www.cnblogs.com/Mr-Lyu/p/5736152.html https://blog.csdn.net/yf198708/article/details/51 ...

  7. 从一个LocalDateTime引发的疑问

    一 公司有同事部署出错,然后查日志,找时间,从k8s得到的时间是  2017-06-16T09:38:48.580 +0000,然后他就纳闷了,因为他根本不会在9点部署好吧,而且9点大多数程序员都没开 ...

  8. FloatHelper

    function FloatHelper() { } FloatHelper.prototype.showFloater = function (Target, Title, Action, Acti ...

  9. sqlserver 数据库 的数据库个数统计 表个数统计 表的数据量统计(转载)

    http://www.cnblogs.com/qinche/archive/2012/08/09/app.html 由于今天要监控数据,急需统计实例中1有多少库2库里有多少表3每个表有多少数据 --将 ...

  10. swift 监听键盘弹出的高度

    // 监听键盘通知 NotificationCenter.default.addObserver(self, selector: #selector(ComposeViewController.key ...