zoukankan      html  css  js  c++  java
  • 【NOI2016】优秀的拆分

    题面

    https://www.luogu.org/problem/P1117

    题解

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 305000
    
    int log[69500],st[N],en[N];
    char ts[N],s[N];
    
    struct SuffixArray {
      int n,m,rank[N],sa[N],tax[N],tp[N],height[N];
      int minh[N][20];
      char s[N];
      void clear() {
        memset(s,0,sizeof(s));
        memset(minh,0,sizeof(minh));
        memset(rank,0,sizeof(rank));
        memset(sa,0,sizeof(sa));
        memset(tax,0,sizeof(tax));
        memset(tp,0,sizeof(tp));
        memset(height,0,sizeof(height));
      }
      void cntsort() {
        for (int i=0;i<=m;i++) tax[i]=0;
        for (int i=1;i<=n;i++) tax[rank[i]]++;
        for (int i=1;i<=m;i++) tax[i]+=tax[i-1];
        for (int i=n;i>=1;i--) sa[tax[rank[tp[i]]]--]=tp[i];
      }
      void suffixsort() {
        m=30;
        for (int i=1;i<=n;i++) rank[i]=s[i]-'a'+1,tp[i]=i;
        cntsort();
        for (int w=1,p=0;p<n;m=p,w<<=1) {
          p=0;
          for (int i=1;i<=w;i++) tp[++p]=n-w+i;
          for (int i=1;i<=n;i++) if (sa[i]>w) tp[++p]=sa[i]-w;
          cntsort();
          swap(tp,rank);
          rank[sa[1]]=p=1;
          for (int i=2;i<=n;i++) 
            rank[sa[i]]=(tp[sa[i-1]]==tp[sa[i]] && tp[sa[i-1]+w]==tp[sa[i]+w]) ? p:++p;
        }
      }
      void getheight() {
        int k=0;
        for (int i=1;i<=n;i++) {
          if (k) k--;
          int j=sa[rank[i]-1];
          while (s[i+k]==s[j+k]) k++;
          height[rank[i]]=k;
        }
      }
      void build() {
        int i,j;
        for (i=1;i<=n;i++) minh[i][0]=height[i];
        for (i=1;i<=16;i++) {
          int len=(1<<(i-1));
          for (j=1;j<=n;j++) minh[j][i]=min(minh[j][i-1],minh[j+len][i-1]);
        }
      }
      int lcp(int x,int y) {
        x=rank[x],y=rank[y];
        if (x>y) swap(x,y);
        if (x==y) return 0;
        int cnt=log[y-x]-1;
        return min(minh[x+1][cnt],minh[y-(1<<cnt)+1][cnt]);
      }
    } a,b;
    
    int main(){
      int nx,x;
      log[0]=0;
      log[1]=1;
      x=1;
      for (int i=1;i<=15;i++) {
        nx=(1<<(i+1))-1;
        for (int j=x+1;j<=nx;j++) log[j]=i+1;
        x=nx;
      }
      int T;
      scanf("%d",&T);
      while (T--) {
        memset(st,0,sizeof(st));
        memset(en,0,sizeof(en));
        a.clear(); b.clear();
        scanf("%s",s+1);
        int l=a.n=b.n=strlen(s+1);
        for (int i=1;i<=l;i++) a.s[i]=s[i]; a.s[l+1]='';
        for (int i=1;i<=l;i++) b.s[l-i+1]=s[i]; b.s[l+1]='';
        a.suffixsort(); a.getheight(); a.build();
        b.suffixsort(); b.getheight(); b.build();
        for (int L=1;L<=l/2;L++) {
          for(int i=L,j=i+L;j<=l;i+=L,j+=L) {
            int x=min(a.lcp(i,j),L),y=min(b.lcp(l-(i-1)+1,l-(j-1)+1),L-1);
            int t=x+y-L+1;
            if(x+y>=L) {
              st[i-y]++; st[i-y+t]--;
              en[j+x-t]++; en[j+x]--;
            }
          }
        }
        for (int i=1;i<=l;i++) st[i]+=st[i-1],en[i]+=en[i-1];
        ll ans=0;
        for (int i=1;i<=l;i++) ans+=en[i]*1LL*st[i+1];
        cout<<ans<<endl;
      }
    }
  • 相关阅读:
    systabcontrol32
    winform 进程唯一,打开第二个激活第一个进程的窗体显示
    winform在 Xp下杀死进程
    安装包创建桌面快捷方式
    [最短路/线段树大法优化DIJ] 【模板】单源最短路径(标准版)
    [线段树模板题] 线段树2
    [线段树优化应用] 数星星Star
    [倍增思想/变种最短路] 跑路
    [DP/变种背包] SOFTWARE
    [前缀和/数论] 数列
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11427263.html
Copyright © 2011-2022 走看看