LINK:波波老师

LINK:同bzoj 1396 识别子串

不过前者要求线性做法 后者可以log过。实际上前者也被我一个log给水过了.

其实不算很水 我自认跑的很快罢了.

都是求经过一个位置的最短的 在整个字符串中只出现过一次的子串。

SAM很容易完成这个东西.

考虑对于计算每个节点的贡献 容易发现是一个区间整体赋值和一个等差数列 不过太懒了不想维护这个等差数列 我反着建SAM维护最右左端点了。

就变成了两个区间最值问题。完全可以标记永久化 可能有点卡空间。

当然考场上也思考了O(n)的做法 先考虑等差数列那个地方 由于right集大小为1 那么显然这个点的len是一直到之后都有效所以可以直接标记最后取max

考虑区间取min操作。当时想法是排序后利用并查集 排列可以利用桶排 然后复杂度就降到\(n\cdor (a)\)

可以发现桶排序之后可以利用单调队列+链表 来实现O(n).细节有点繁琐 不再赘述.

标记永久化还是很快滴 (比其他dalao写zkw线段树要快一点.当时我也想写zkw线段树 不过不太熟练所以就没用

const int MAXN=5000010;
int n,cnt=1,last=1;
int sum[MAXN<<2],w[MAXN<<2];//一个取max 一个取min.
struct wy
{
int ch[5];
int fa,len;
}t[MAXN<<1];
char a[MAXN];ll ans;
int c[MAXN],vis[MAXN<<1],s[MAXN<<1];
inline void insert(int x)
{
int p=last;
int np=last=++cnt;
len(np)=len(p)+1;
while(p&&!t[p].ch[x])
{
t[p].ch[x]=np;
p=f(p);
}
if(!p)f(np)=1;
else
{
int q=t[p].ch[x];
if(len(q)==len(p)+1)f(np)=q;
else
{
int nq=++cnt;
t[nq]=t[q];
len(nq)=len(p)+1;
f(np)=f(q)=nq;
while(p&&t[p].ch[x]==q)
{
t[p].ch[x]=nq;
p=f(p);
}
}
}
}
inline void topsort()
{
rep(1,cnt,i)++c[len(i)];
rep(1,n,i)c[i]+=c[i-1];
rep(1,cnt,i)s[c[len(i)]--]=i;
}
inline void change(int p,int l,int r,int L,int R,int x)
{
if(l==L&&r==R)return sum[p]=min(sum[p],x),void();
int mid=(l+r)>>1;
if(L>mid)return change(yy,mid+1,r,L,R,x),void();
if(R<=mid)return change(zz,l,mid,L,R,x),void();
change(zz,l,mid,L,mid,x);change(yy,mid+1,r,mid+1,R,x);
}
inline void modify(int p,int l,int r,int L,int R,int x)
{
if(l==L&&r==R)return w[p]=max(w[p],x),void();
int mid=(l+r)>>1;
if(L>mid)return modify(yy,mid+1,r,L,R,x),void();
if(R<=mid)return modify(zz,l,mid,L,R,x),void();
modify(zz,l,mid,L,mid,x);modify(yy,mid+1,r,mid+1,R,x);
}
inline void dfs(int p,int l,int r,int S,int W)
{
S=min(S,sum[p]);W=max(W,w[p]);
if(l==r)
{
if(W==0)W=-INF;
ans+=min(S,l-W+1);
return;
}
int mid=(l+r)>>1;
dfs(zz,l,mid,S,W);
dfs(yy,mid+1,r,S,W);
}
int main()
{
freopen("bobo.in","r",stdin);
freopen("bobo.out","w",stdout);
gc(a);n=strlen(a+1);
fep(n,1,i)insert(a[i]-'a'),vis[last]=i;
topsort();
memset(sum,0x3f,sizeof(sum));
fep(cnt,2,i)
{
int x=s[i];
//cout<<vis[x]<<' '<<len(x)<<endl;
if(vis[x]==-1)vis[f(x)]=-1;
else
{
if(!vis[f(x)])vis[f(x)]=vis[x];
else vis[f(x)]=-1;
}
if(vis[x]!=-1)
{
change(1,1,n,vis[x],vis[x]+len(f(x)),len(f(x))+1);
modify(1,1,n,vis[x]+len(f(x)),vis[x]+len(x)-1,vis[x]);
}
}
dfs(1,1,n,INF,0);putl(ans);
return 0;
}

最新文章

  1. 在Oracle中恢复被DROP掉的表
  2. MCMC 、抽样算法与软件实现
  3. C#面试(2016年4月)
  4. Restful api介绍
  5. Windows环境下 PHP+Apache+Mysql配置
  6. SQL2005 遍历表插入
  7. Android SQLite数据库版本升级原理解析
  8. 山东理工大学第七届ACM校赛-飞花的鱼塘 分类: 比赛 2015-06-26 10:30 43人阅读 评论(0) 收藏
  9. 各种ORM安装
  10. C++ 头文件系列(iosfwd)
  11. 关于学习Python的一些心得
  12. SpringBoot基础系列-SpringCache使用
  13. Vs2013 使用EF6 连接mysql数据库
  14. rmq问题模板处理
  15. Java基础学习-关键字的概述和特点以及常量的概述和分类
  16. python编码(二)
  17. 布谷鸟搜索算法CS
  18. Android Hawk数据库 github开源项目
  19. 【Android】3.14 公交线路查询功能
  20. PHP代码审计 -1.SQL注入总结

热门文章

  1. 整理一下CSS最容易躺枪的二十规则,大家能躺中几条?
  2. Spark TempView和GlobalTempView的区别
  3. 面向对象之多态(Java实现)
  4. 消息队列-一篇读懂rabbitmq(生命周期,confirm模式,延迟队列,集群)
  5. 数据可视化之powerBI入门(九)PowerBI数据建模:其实一点都不高深
  6. Django之重写用户模型
  7. The solution for apt-get update Err 404
  8. OSCP Learning Notes - Privilege Escalation
  9. Harbor打怪升级
  10. /dev/mapper/VolGroup00-LogVol00 满了,根目录存储垃圾文件导致磁盘满了