zoukankan      html  css  js  c++  java
  • bzoj3756: Pty的字符串

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 #define maxn 800005
      7 #define maxm 1600005
      8 #define maxl 1600005
      9 #define ll long long
     10 using namespace std;
     11 int n,cnt,m,last,root,tot,val[maxl],now[maxn],son[maxl],prep[maxl],ri[maxm],fa[maxm],dist[maxm],tmp[maxm];
     12 ll sum[maxm],ans;
     13 char st[maxn*20];
     14 struct Tsegment{
     15     int son[maxm][3];
     16     void prepare(){tot=last=root=1,memset(ri,0,sizeof(ri)),memset(son,0,sizeof(son)),memset(dist,0,sizeof(dist));}
     17     int newnode(int x){
     18         dist[++tot]=x; return tot;
     19     }
     20     int add(int x,int p){
     21         int q=son[p][x];
     22         if (q==0){
     23             int np=newnode(dist[p]+1); last=np; ri[np]=1;
     24             for (;p&&!son[p][x];p=fa[p]) son[p][x]=np;
     25             if (p==0) fa[np]=root;
     26             else{
     27                 int q=son[p][x];
     28                 if (dist[p]+1==dist[q]) fa[np]=q;
     29                 else{
     30                     int nq=newnode(dist[p]+1);
     31                     memcpy(son[nq],son[q],sizeof(son[q]));
     32                     fa[nq]=fa[q],fa[q]=fa[np]=nq;
     33                     for (;p&&son[p][x]==q;p=fa[p]) son[p][x]=nq;    
     34                 }
     35             }
     36         }else{
     37             if (dist[p]+1==dist[q]) last=q,ri[q]++;
     38             else{
     39                 int nq=newnode(dist[p]+1); last=nq; ri[nq]=1;
     40                 memcpy(son[nq],son[q],sizeof(son[q]));
     41                 fa[nq]=fa[q],fa[q]=nq;
     42                 for (;p&&son[p][x]==q;p=fa[p]) son[p][x]=nq;
     43             }
     44         }
     45         return last;
     46     }
     47     void Tsort(){
     48         memset(sum,0,sizeof(sum));
     49         for (int i=1;i<=tot;i++) sum[dist[i]]++;
     50         for (int i=1;i<=n;i++) sum[i]+=sum[i-1];
     51         for (int i=1;i<=tot;i++) tmp[sum[dist[i]]--]=i;
     52         memset(sum,0,sizeof(sum));
     53         for (int x,i=tot;i>=1;i--){
     54             x=tmp[i];
     55             if (fa[x]) ri[fa[x]]+=ri[x];
     56         }
     57         ri[root]=0,dist[root]=dist[0]=0;
     58         for (int x,i=1;i<=tot;i++){
     59             x=tmp[i];
     60             sum[x]=ri[x]*(dist[x]-dist[fa[x]]);
     61             if (fa[x]) sum[x]+=sum[fa[x]];
     62         }
     63         sum[root]=0;
     64     }
     65     void work(){
     66         int len=0; last=root; ans=0;
     67         for (int x,i=1;i<=m;i++){
     68             x=st[i]-'a';
     69             if (son[last][x]) len++,last=son[last][x];
     70             else{
     71                 for (;last&&!son[last][x];last=fa[last]);
     72                 if (last==0) last=root,len=0;
     73                 else{
     74                     len=dist[last]+1,last=son[last][x];
     75                 }
     76             }
     77             if (last!=root&&last){
     78                 ans+=(sum[fa[last]]+(len-dist[fa[last]])*ri[last]);
     79             }
     80         }
     81         printf("%lld
    ",ans);
     82     }
     83 }SAM;
     84 struct Graph{
     85     void add(int x,int y,int z){
     86         cnt++,prep[cnt]=now[x],now[x]=cnt,son[cnt]=y,val[cnt]=z;
     87     }
     88     void dfs(int x,int goal){
     89         for (int i=now[x],so=son[i];i;i=prep[i],so=son[i]){
     90             int p=SAM.add(val[i],goal);
     91             dfs(so,p);
     92         }
     93     }
     94 }G;
     95 int main(){
     96     scanf("%d",&n);
     97     cnt=ans=0,memset(now,0,sizeof(now));
     98     for (int i=2,u,v;i<=n;i++){
     99         scanf("%d%s",&u,st+1);
    100         G.add(u,i,st[1]-'a');
    101     }
    102     SAM.prepare();
    103     G.dfs(1,1);
    104     SAM.Tsort();
    105     scanf("%s",st+1),m=strlen(st+1);
    106     SAM.work();
    107     return 0;
    108 }
    View Code

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3756

    题目大意:

    在神秘的东方有一棵奇葩的树,它有一个固定的根节点(编号为1)。树的每条边上都是一个字符,字符为a,b,c中的一个,你可以从树上的任意一个点出发,然后沿着远离根的边往下行走,在任意一个节点停止,将你经过的边的字符依次写下来,就能得到一个字符串,例如:
     
    在这棵树中我们能够得到的字符串是:
    c, cb, ca, a, b, a
    现在pty得到了一棵树和一个字符串S。如果S的一个子串[l,r]和树上某条路径所得到的字符串完全相同,则我们称这个子串和该路径匹配。现在pty想知道,S的所有子串和树上的所有路径的匹配总数是多少?
    做法:看到此题,我们可以发现,先将题目中给定的trie树建立一个广义后缀自动机,预处理出每个点的right值,dist值,sum值,前两个都是后缀自动机自带的,不用说了,sum表示parent树中该点到根节点的路径上所有的字符串的数目(能使后面的复杂度降至O(n)级别的),然后用输入的字符串在SAM上匹配即可,与普通匹配相似,但是统计答案不一样,ans+=(sum【fa【x】】+right【x】*(len-dist【x】)),x表示走到的点,len表示匹配的长度,为什么呢?除了要将走到的状态带来的答案外,parent树中这个点的祖先节点都能完全匹配到,所以要加上sum【fa【x】】。记得sum和ans要开long long 。
    做法:广义后缀自动机。
  • 相关阅读:
    vim——打开多个文件、同时显示多个文件、在文件之间切换(转)
    内核任务调度与数据结构
    chrome浏览器iframe兼容性问题,隐藏起来再显示滚动条消失?
    九、迭代器、生成器、函数递归调用与二分法
    八、函数、闭包、装饰器
    七、函数
    六、字符编码、文件
    五、列表、元组、字典、集合详解
    四、字符串及其内置方法
    三、内存管理、数据类型、基本运算符、流程控制
  • 原文地址:https://www.cnblogs.com/OYzx/p/5557390.html
Copyright © 2011-2022 走看看