zoukankan      html  css  js  c++  java
  • BZOJ3620 似乎在梦中见过的样子[KMP]

    吐槽

    迷惑行为大赏。。。

    想好的$O(n^2)$暴力没敢写,结果正解就是15000卡常过$O(n^2)$。。

    还耗了我一节课想SA的$O(n ext{log}n)$做法没想出来。。。


    这题其实和动物园差不多,所谓$A+B+A$形式其实就是对于$i,j$,$exists x in [i,j]$使得$s[i...x]=s[j-(x-i),j]$且$x< j-(x-i)-1$。

    于是变形式子得到关系式,就正常维护两个匹配的指针$j,k$进行匹配即可,$2k < i+j-1$且$s[k]=s[i]$即可匹配。

    接下来要做的就是卡常。。其实kmp常数已经蛮小的啦,所以我不会卡常也过了。但其实我是榜底

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define dbg(x,y,z) cerr << #x << " = " << x << "  " << #y << " = " << y << "  " << #z << " = " << z <<endl
     7 using namespace std;
     8 typedef long long ll;
     9 typedef double db;
    10 typedef pair<int,int> pii;
    11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    16 template<typename T>inline T read(T&x){
    17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    19 }
    20 const int N=15000+7;
    21 char s[N];
    22 int nxt[N];
    23 int n,lim,ans;
    24 inline void solve(int l){
    25     nxt[l]=l-1;//dbg(l,0,0);
    26     for(register int i=l+1,j=l-1,k=l-1;i<=n;++i){//dbg(i,j,k);
    27         while(j>=l&&s[j+1]^s[i])j=nxt[j];
    28         while(k>=l&&(s[k+1]^s[i]||k+1>=(l+i)>>1))k=nxt[k];
    29         nxt[i]=s[j+1]^s[i]?l-1:++j;
    30         s[k+1]==s[i]&&k+1<(l+i)>>1&&++k;
    31         if(k-l+1>=lim)++ans;
    32     }
    33 }
    34 
    35 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
    36     scanf("%s",s+1),read(lim);n=strlen(s+1);
    37     for(register int i=1;i<=n-lim-lim;++i)solve(i);
    38     return printf("%d
    ",ans),0;
    39 }
    厚颜无耻放上贼慢的code

    Upd:知道自己为什么常数大了。其实那个$k$没有必要加进去。考虑每个$i$尝试找最短的满足要求的前缀并且长度要$ge k$。由于$next$指针可以看做一棵树,也就是求根到节点的路径上第一个出现的$ge k$长度的前缀是否到了当前串长的一半。

    那么可以用$fa[i]$表示在自己到祖先的所有前缀中最小的、长度$ge k$的前缀是哪个,检查一下合法性即可。这其实是一个fail树思想的应用

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define dbg(x) cerr << #x << " = " << x <<endl
     7 using namespace std;
     8 typedef long long ll;
     9 typedef double db;
    10 typedef pair<int,int> pii;
    11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    16 template<typename T>inline T read(T&x){
    17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    19 }
    20 const int N=15000+7,INF=114514;
    21 char s[N];
    22 int nxt[N],fa[N];
    23 int n,lim,ans;
    24 inline void solve(int l){
    25     nxt[l]=l-1,fa[l-1]=fa[l]=INF;
    26     for(register int i=l+1,j=l-1;i<=n;++i){
    27         while(j^(l-1)&&s[j+1]^s[i])j=nxt[j];
    28         nxt[i]=s[j+1]^s[i]?j:++j;
    29         fa[i]=j<l+lim-1?INF:_min(j,fa[j]);
    30         if(fa[i]<<1<l+i-1)++ans;
    31     }
    32 }
    33 
    34 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
    35     scanf("%s",s+1),read(lim);n=strlen(s+1);
    36     for(register int i=1;i<=n-lim-lim;++i)solve(i);
    37     return printf("%d
    ",ans),0;
    38 }
    优化后

    所以我放那么多时间在一个水题上有什么意义。

  • 相关阅读:
    WSS页面定制系列(1)如何启用表单页面的编辑模式
    [转载]Customizing the Context Menu of Document Library Items
    MOSS publishing功能:创建页面到子文件夹
    CodeArt.SharePoint.CamlQuery_0.9发布(源码)
    WSS页面定制系列(2)定制单个列表的表单页面
    WSS页面定制系列(3)重写表单的保存逻辑
    MOSS字段编辑权限控制方案(3)重写表单字段呈现逻辑
    WSS(MOSS)如何修改Rich文本编辑器的宽度
    web录音的实现
    WSS 扩展文件夹的属性如何给文件夹添加扩展字段
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11506714.html
Copyright © 2011-2022 走看看