bzoj 5512
Posted zhangleo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 5512相关的知识,希望对你有一定的参考价值。
后缀自动机基本应用
对询问串建起后缀自动机,然后建起parent树,做一次子树统计就知道了每个节点代表的字符串出现次数
接下来我们只考虑出现次数等于$k$的那些点,对于任意一个点$p$我们知道他代表的子串长度是连续的,长度范围在$[len_fa+1,len_p]$之间,那么我们做个差分,最后统计一次就知道每个长度出现次数了
时间复杂度$O(n)$
代码:
#include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <vector> using namespace std; struct node int tranc[27]; int len,pre,endpos; s[200005]; int tot,las; int maxans,maxp; int T,n,k; int f[200005]; int S[200005]; char ch[100005]; vector <int> v[200005]; void ins(int c) int nwp=++tot; s[nwp].len=s[las].len+1; s[nwp].endpos=1; int lsp; for(lsp=las;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)s[lsp].tranc[c]=nwp; if(!lsp)s[nwp].pre=1; else int lsq=s[lsp].tranc[c]; if(s[lsq].len==s[lsp].len+1)s[nwp].pre=lsq; else int nwq=++tot; s[nwq]=s[lsq]; s[nwq].endpos=0; s[nwq].len=s[lsp].len+1; s[lsq].pre=s[nwp].pre=nwq; while(s[lsp].tranc[c]==lsq)s[lsp].tranc[c]=nwq,lsp=s[lsp].pre; las=nwp; void init() for(int i=1;i<=tot;i++)memset(s[i].tranc,0,sizeof(s[i].tranc)),s[i].len=s[i].pre=s[i].endpos=0; for(int i=1;i<=tot;i++)v[i].clear(); memset(S,0,sizeof(S)); tot=las=1; maxans=maxp=-0x3f3f3f3f; void buildtree() for(int i=2;i<=tot;i++)v[s[i].pre].push_back(i); int query() int maxp=-1,maxv=0; for(int i=1;i<=n;i++) S[i]+=S[i-1]; if(S[i]>=maxv&&S[i])maxv=S[i],maxp=i; return maxp; void dfs(int x) for(int i=0;i<v[x].size();i++) int to=v[x][i]; dfs(to); s[x].endpos+=s[to].endpos; if(s[x].endpos==k&&x!=1)S[s[s[x].pre].len+1]++,S[s[x].len+1]--; void solve() scanf("%s",ch+1); n=strlen(ch+1),scanf("%d",&k); for(int i=1;i<=n;i++)ins(ch[i]-‘a‘+1); buildtree(),dfs(1); printf("%d\n",query()); int main() scanf("%d",&T); while(T--)init(),solve(); return 0;
以上是关于bzoj 5512的主要内容,如果未能解决你的问题,请参考以下文章
考后反思(bzoj3940 bzoj4899 bzoj3307)