题面:http://www.lydsy.com/JudgeOnline/problem.php?id=2806
大神的题解:http://blog.youkuaiyun.com/acdreamers/article/details/10833181
不过维护单调队列的那一段好像错了?
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define M 2500010
#define N 5000010
using namespace std;
int mx[M],f[M],q[M],n,m,ans;
char str[M];
struct Suffix_Automan{
int root,cnt,last,ch[N][3],dep[N],fa[N];
inline int newnode(int deep){
dep[++cnt]=deep;
return cnt;
}
void init(){
last=root=cnt=1;
}
void ins(int x){
int p=newnode(dep[last]+1);
int u=last;
for (;u&&!ch[u][x];u=fa[u]) ch[u][x]=p;
if (!u) fa[p]=root;
else {
int q=ch[u][x];
if (dep[q]==dep[u]+1) fa[p]=q;
else{
int nq=newnode(dep[u]+1);
fa[nq]=fa[q];
fa[q]=fa[p]=nq;
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
for (;u&&ch[u][x]==q;u=fa[u]) ch[u][x]=nq;
}
}
last=p;
}
void match(){
int ro=root,tmp=0;
for (int i=0;str[i];i++){
int x=str[i]-'0';
if (ch[ro][x]) tmp++,ro=ch[ro][x];
else {
for (;ro&&!ch[ro][x];ro=fa[ro]);
if (ch[ro][x]) tmp=dep[ro]+1,ro=ch[ro][x];
else tmp=0,ro=root;
}
mx[i+1]=tmp;
}
}
bool judge(int lmt,int len){
int he,ta,r;
f[0]=q[ta=0]=0;
he=ta+1;
for (int i=1;i<=len;i++){
f[i]=f[i-1],r=i-lmt;
if (r>=0){
for (;he<=ta&&f[r]-r>f[q[ta]]-q[ta];ta--);
q[++ta]=r;
}
while (he<=ta&&q[he]<i-mx[i]) he++;
if (he<=ta) f[i]=max(f[i],f[q[he]]+i-q[he]);
}
return f[len]*10>=len*9;
}
}SAM;
inline int getstr(){
int len=0;
while (!isdigit((str[len]=getchar())));
len++;
while (isdigit((str[len++]=getchar())));
str[--len]=0;
return len;
}
int main(){
scanf("%d%d",&n,&m);
SAM.init();
for (;m;m--){
getstr();
for (int i=0;str[i];i++) SAM.ins(str[i]-'0');
SAM.ins(2);
}
for (;n;n--){
int len=getstr();
SAM.match();
int l=0,r=len;
ans=0;
while (l<=r){
int mid=(l+r)>>1;
if (SAM.judge(mid,len)){
l=mid+1;
ans=mid;
}
else r=mid-1;
}
printf("%d\n",ans);
}
}

该博客主要探讨了如何利用后缀自动机与动态规划相结合的方法解决BZOJ2806题目。博主分享了题目的链接以及一位大神的题解,并指出题解中关于单调队列维护的部分可能存在错误。同时,提供了获得AC(Accepted)的代码。
828

被折叠的 条评论
为什么被折叠?



