zoukankan      html  css  js  c++  java
  • 洛谷P4218 [CTSC2010]珠宝商(后缀自动机+点分治)

    传送门

    这题思路太清奇了……->题解

      1 //minamoto
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<cmath>
      7 #define ll long long
      8 using namespace std;
      9 inline int read(){
     10     #define num ch-'0'
     11     char ch;bool flag=0;int res;
     12     while(!isdigit(ch=getchar()))
     13     (ch=='-')&&(flag=true);
     14     for(res=num;isdigit(ch=getchar());res=res*10+num);
     15     (flag)&&(res=-res);
     16     #undef num
     17     return res;
     18 }
     19 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
     20 const int N=1e5+5;
     21 char str[N],s[N];
     22 ll ans=0;
     23 int ver[N],Next[N],head[N],tot=0;
     24 int sqr,id1[N],id2[N];
     25 inline void add(int u,int v){
     26     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
     27 }
     28 int vis[N],rt,son[N],sz[N],size,n,m;
     29 struct SAM{
     30     int rt,last,tot,ch[N][26],fa[N],l[N],cnt[N];
     31     int s[N],tag[N],son[N][26],le[N];
     32     SAM(){rt=last=tot=1;}
     33     int ins(int c){
     34         int p=last,np=++tot;last=np,le[np]=l[np]=l[p]+1,cnt[np]=1;
     35         for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
     36         if(!p) fa[np]=rt;
     37         else{
     38             int q=ch[p][c];
     39             if(l[q]==l[p]+1) fa[np]=q;
     40             else{
     41                 int nq=++tot;
     42                 memcpy(ch[nq],ch[q],sizeof(ch[q]));
     43                 l[nq]=l[p]+1,le[nq]=le[q];
     44                 fa[nq]=fa[q],fa[q]=fa[np]=nq;
     45                 for(;p&&ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
     46             }
     47         }
     48         return last;
     49     }
     50     int a[N],c[N];
     51     void calc(){
     52         for(int i=1;i<=tot;++i) ++c[l[i]];
     53         for(int i=1;i<=tot;++i) c[i]+=c[i-1];
     54         for(int i=tot;i;--i) a[c[l[i]]--]=i;
     55         for(int i=tot,p;i>=2;--i){
     56             p=a[i];
     57             cnt[fa[p]]+=cnt[p];
     58             son[fa[p]][s[le[p]-l[fa[p]]]]=p;
     59         }
     60     }
     61     void mark(int u,int fa,int now,int len){
     62         if(!now) return;
     63         if(len==l[now]) now=son[now][str[u]-'a'];
     64         else if(s[le[now]-len]!=str[u]-'a') now=0;
     65         if(!now) return;
     66         ++tag[now];
     67         for(int i=head[u];i;i=Next[i]){
     68             int v=ver[i];
     69             if(v!=fa&&!vis[v]) mark(v,u,now,len+1);
     70         }
     71     }
     72     inline void push(){for(int i=1;i<=tot;++i) tag[a[i]]+=tag[fa[a[i]]];}
     73 }sam1,sam2;
     74 void findrt(int u,int fa){
     75     sz[u]=1,son[u]=0;
     76     for(int i=head[u];i;i=Next[i]){
     77         int v=ver[i];
     78         if(v!=fa&&!vis[v])
     79         findrt(v,u),sz[u]+=sz[v],cmax(son[u],sz[v]);
     80     }
     81     cmax(son[u],size-sz[u]);
     82     if(!rt||son[u]<son[rt]) rt=u;
     83 }
     84 int num=0,g[N];
     85 void get(int u,int fa){
     86     g[++num]=u;
     87     for(int i=head[u];i;i=Next[i]){
     88         int v=ver[i];
     89         if(v!=fa&&!vis[v]) get(v,u);
     90     }
     91 }
     92 void getsum(int u,int fa){
     93     ++size;
     94     for(int i=head[u];i;i=Next[i]){
     95         int v=ver[i];
     96         if(v!=fa&&!vis[v]) getsum(v,u);
     97     }
     98 }
     99 void dfs(int u,int fa,int now){
    100     now=sam1.ch[now][str[u]-'a'];
    101     if(!now) return;
    102     ans+=sam1.cnt[now];
    103     for(int i=head[u];i;i=Next[i]){
    104         int v=ver[i];
    105         if(v!=fa&&!vis[v]) dfs(v,u,now);
    106     }
    107 }
    108 void work(int u,int fa,int op){
    109     for(int i=1;i<=sam1.tot;++i) sam1.tag[i]=0;
    110     for(int i=1;i<=sam2.tot;++i) sam2.tag[i]=0;
    111     int to=str[fa]-'a';
    112     if(fa) sam1.mark(u,fa,sam1.son[1][to],1),sam2.mark(u,fa,sam2.son[1][to],1);
    113     else sam1.mark(u,fa,1,0),sam2.mark(u,fa,1,0);
    114     sam1.push(),sam2.push();
    115     for(int i=1;i<=m;++i) ans+=1ll*op*sam1.tag[id1[i]]*sam2.tag[id2[m-i+1]];
    116 }
    117 void solve(int u){
    118     if(size<=sqr){
    119         num=0,get(u,0);
    120         for(int i=1;i<=num;++i) dfs(g[i],0,sam1.rt);
    121         return;
    122     }
    123     vis[u]=1,work(u,0,1);
    124     for(int i=head[u];i;i=Next[i])
    125     if(!vis[ver[i]]) work(ver[i],u,-1);
    126     for(int i=head[u];i;i=Next[i]){
    127         int v=ver[i];
    128         if(vis[v]) continue;
    129         size=0,getsum(v,u);
    130         rt=0,findrt(v,u);
    131         solve(rt);
    132     }
    133 }
    134 int main(){
    135 //    freopen("testdata.in","r",stdin);
    136     n=read(),m=read();
    137     for(int i=1,u,v;i<n;++i)
    138     u=read(),v=read(),add(u,v),add(v,u);
    139     scanf("%s",str+1),scanf("%s",s+1);
    140     for(int i=1;i<=m;++i) sam1.s[i]=s[i]-'a',id1[i]=sam1.ins(s[i]-'a');
    141     reverse(s+1,s+1+m);
    142     for(int i=1;i<=m;++i) sam2.s[i]=s[i]-'a',id2[i]=sam2.ins(s[i]-'a');
    143     sam1.calc(),sam2.calc();
    144     rt=0,son[0]=n+1,size=n,sqr=sqrt(n);
    145     findrt(1,0),solve(rt);
    146     printf("%lld
    ",ans);
    147     return 0;
    148 }
  • 相关阅读:
    Winform WebBrowser引用IE版本问题
    MarkdownPad怎么显示表格
    C# winForm里窗体嵌套
    code first 创建数据库
    mvc+webapi+dapper+ef codefirst项目搭建
    MongoDB:逐渐变得无关紧要
    fiddler打开后 浏览器就上不了网的解决方法
    Android学习系列(16)--App列表之圆角ListView
    Android应用程序结构总结
    android程序监听home键与电源键
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9648945.html
Copyright © 2011-2022 走看看