zoukankan      html  css  js  c++  java
  • LOJ#2083. 「NOI2016」优秀的拆分

    $n leq 30000$的字符串,问其所有子串的所有AABB形式的拆分有多少种。$t leq 10$组询问。

    $n^3$过80,$n^2$过95,鬼去写正解。。

    $n^2$:先枚举一次算每个位置结尾的AA形式的子串,再枚举一次用类似的方法算答案。

    正解:类似,记每个位置结尾的AA的子串和每个位置开头的即可。算这个数组可用如此方法:枚举A长度$L$,每A个位置标记一个关键点。然后相邻两个关键点$a,b$,找前缀$a,b$的最长公共后缀$p$和后缀$a,b$的最长公共前缀$s$,若$p+s>L$说明这里有一些A,其中作为起点的范围是$[a-p+1,a+s-L]$,作为终点的范围$[b-p+L,b+s-1]$,相当于做了个区间加,可以差分。这样做的话,复杂度就变成$frac{n}{1}+frac{n}{2}+...=n ln n$了。

    找最长公共前后缀,sa或二分hash或sam均可。

      1 //#include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 //#include<math.h>
      5 //#include<set>
      6 //#include<queue>
      7 //#include<bitset>
      8 //#include<vector>
      9 #include<algorithm>
     10 #include<stdlib.h>
     11 using namespace std;
     12 
     13 #define LL long long
     14 int qread()
     15 {
     16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
     17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
     18 }
     19 
     20 //Pay attention to '-' , LL and double of qread!!!!
     21 
     22 int T,n;
     23 #define maxn 60011
     24 char s[maxn]; int f[maxn],g[maxn];
     25 
     26 struct SAM
     27 {
     28     struct Node{int pre,ch[26],pos,Max;}a[maxn];
     29     int size,last;
     30     void clear()
     31     {
     32         size=last=0; a[0].pre=-1; a[0].pos=a[0].Max=0; memset(a[0].ch,0,sizeof(a[0].ch));
     33         le=2; memset(first,0,sizeof(first));
     34     }
     35     int pp[maxn];
     36     void insert(int c,int p)
     37     {
     38         int x=++size,y=last; memset(a[x].ch,0,sizeof(a[x].ch));
     39         a[x].Max=a[last].Max+1; a[x].pos=p; pp[p]=x;
     40         last=x;
     41         for (;~y && !a[y].ch[c];y=a[y].pre) a[y].ch[c]=x;
     42         if (!~y) a[x].pre=0;
     43         else if (a[a[y].ch[c]].Max==a[y].Max+1) a[x].pre=a[y].ch[c];
     44         else
     45         {
     46             int z=a[y].ch[c],w=++size; a[w]=a[z]; a[w].pos=p; a[w].Max=a[y].Max+1;
     47             a[z].pre=a[x].pre=w;
     48             for (;~y && a[y].ch[c]==z;y=a[y].pre) a[y].ch[c]=w;
     49         }
     50     }
     51     struct Edge{int to,next;}edge[maxn<<1]; int first[maxn],le;
     52     void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
     53     int Log[maxn<<1],rmq[22][maxn<<1],dep[maxn],Time,id[maxn];
     54     void predfs(int x)
     55     {
     56         rmq[0][++Time]=x; id[x]=Time;
     57         for (int i=first[x];i;i=edge[i].next)
     58         {
     59             Edge &e=edge[i]; dep[e.to]=dep[x]+1;
     60             predfs(e.to); rmq[0][++Time]=x;
     61         }
     62     }
     63     void pre()
     64     {
     65         for (int i=1;i<=size;i++) in(a[i].pre,i);
     66         Time=0; predfs(0);
     67         Log[0]=-1; for (int i=1,to=size*2-1;i<=to;i++) Log[i]=Log[i>>1]+1;
     68         for (int j=1;j<=18;j++)
     69             for (int i=1,to=size*2-(1<<j);i<=to;i++)
     70                 rmq[j][i]=dep[rmq[j-1][i]]>dep[rmq[j-1][i+(1<<(j-1))]]?rmq[j-1][i+(1<<(j-1))]:rmq[j-1][i];
     71     }
     72     int qq(int x,int y)
     73     {
     74         x=id[pp[x]]; y=id[pp[y]]; if (x>y) x^=y^=x^=y; int l=Log[y-x+1];
     75         return a[dep[rmq[l][x]]>dep[rmq[l][y-(1<<l)+1]]?rmq[l][y-(1<<l)+1]:rmq[l][x]].Max;
     76     }
     77 }s1,s2;
     78 //1 shi zheng de , 2 shi fan de
     79 
     80 int main()
     81 {
     82     T=qread();
     83     while (T--)
     84     {
     85         scanf("%s",s+1); n=strlen(s+1);
     86         s1.clear(); s2.clear();
     87         for (int i=1;i<=n;i++) s1.insert(s[i]-'a',i);
     88         for (int i=n;i;i--) s2.insert(s[i]-'a',i);
     89         s1.pre(); s2.pre();
     90         
     91         memset(f,0,sizeof(f));
     92         memset(g,0,sizeof(g));
     93         for (int i=1;i<=n;i++)
     94             for (int j=i;j<=n-i;j+=i)
     95             {
     96                 int k=j+i,p=s1.qq(j,k),s=s2.qq(j,k); p=min(p,i); s=min(s,i);
     97                 if (p+s>i) f[j-p+1]++,f[j+s-i+1]--,g[k-p+i]++,g[k+s]--;
     98             }
     99         
    100         for (int i=1,now=0;i<=n;i++) now+=f[i],f[i]=now;
    101         for (int i=1,now=0;i<=n;i++) now+=g[i],g[i]=now;
    102         LL ans=0;
    103         for (int i=1;i<n;i++) ans+=g[i]*1ll*f[i+1];
    104         printf("%lld
    ",ans);
    105     }
    106     return 0;
    107 }
    View Code
  • 相关阅读:
    OSG-提示“error reading file e:1.jpg file not handled”
    OSG-加载地球文件报0x00000005错误,提示error reading file simple.earth file not handled
    QT-找开工程后,最上方提示the code model could not parse an included file, which might lead to incorrect code completion and highlighting, for example.
    我的书《Unity3D动作游戏开发实战》出版了
    java中无符号类型的第三方库jOOU
    Windows批处理备份mysql数据
    使用 DevTools 时,通用Mapper经常会出现 class x.x.A cannot be cast to x.x.A
    Java版本,Java版本MongoDB驱动,驱动与MongoDB数据库,Spring之间的兼容性
    Jrebel本地激活方法
    wget下载指定网站目录下的所有内容
  • 原文地址:https://www.cnblogs.com/Blue233333/p/9240940.html
Copyright © 2011-2022 走看看