zoukankan      html  css  js  c++  java
  • BZOJ3238: [Ahoi2013]差异

    题解:

    后缀自动机用起来非常好用。。

    首先根到每个特殊点就是原串的前缀(size=1)

    那么我们会发现在parent树上 right集合不断变成后缀

    那么他们的lca就是他们的最长公共后缀

    于是问题变成了树上给n个点求len[lca]的和

    显然dfs一遍就可以完成了

    后缀数组做这题也是比较简单的

    枚举最小值单调栈维护就可以了

    代码:

    #include <bits/stdc++.h>
    #define ll long long
    #define rint register int
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--)
    using namespace std;
    const int N=1.1e6;
    char s[N];
    int size[N],len[N],ch[N][26],sum[N];
    int lst=1,node=1,t[N],a[N],w[N],fa[N],T,k;
    void extend(int c)
    {
      int f=lst,p=++node; lst=p;
      len[p]=len[f]+1; w[p]=size[p]=1;
      while (f&&!ch[f][c]) ch[f][c]=p,f=fa[f];
      if (!f) { fa[p]=1; return;};
      int x=ch[f][c],y=++node;
      if (len[f]+1==len[x]) {fa[p]=x; node--;return;};
      len[y]=len[f]+1; fa[y]=fa[x]; fa[x]=fa[p]=y;
      memcpy(ch[y],ch[x],sizeof(ch[x]));
      while (f&&ch[f][c]==x) ch[f][c]=y,f=fa[f];
    }
    
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout); 
      ios::sync_with_stdio(false);
      cin>>s;
      int n=strlen(s);
      int l=strlen(s);
      dep(i,l,1) extend(s[i-1]-'a');
      rep(i,1,node) t[len[i]]++;
      rep(i,1,node) t[i]+=t[i-1];
      rep(i,1,node) a[t[len[i]]--]=i;
      ll ans=0;
      rep(i,1,n) ans+=1ll*i*(n-1);
      dep(y,node,1)
      {
        int i=a[y];
        size[fa[i]]+=size[i];
        ans-=2ll*w[fa[i]]*size[i]*len[fa[i]];
        w[fa[i]]+=size[i];
      }
      printf("%lld",ans);
      return 0;
    }
  • 相关阅读:
    Android_方向传感器
    Android 网络图片查看器与网页源码查看器
    SQLite数据库_实现简单的增删改查
    Android 解析JSON
    多线程
    并发编程
    幂等性
    Django缓存机制
    计算机基础
    RESTful规范
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9351816.html
Copyright © 2011-2022 走看看