zoukankan      html  css  js  c++  java
  • [校内训练19_09_02]原样输出

    题意

    给出n个字符串,每个字符串的开头和结尾可以去除一些连续的子串,也可以不删。问这样删去后连成的不同字符串有多少个。要求线性。


    思考

    如果是一个字符串,那么建一颗SAM即可。

    因为是几个字符串拼在一起,那么在某个字符串的SAM上的某一个点,随时都可以跳到下一个字符串的SAM上的某个一点。那么从后往前建SAM,第i颗SAM往第i+1颗SAM连边。

    统计用了拓扑。


    代码

      1 // luogu-judger-enable-o2
      2 // luogu-judger-enable-o2
      3 #define mod 1000000007
      4 #include<bits/stdc++.h>
      5 using namespace std;
      6 const int maxn=2E6+5;
      7 typedef long long int ll;
      8 int n,k,tot,root;
      9 int size,wait[maxn];
     10 int GG[maxn*2];
     11 int in[maxn*2];
     12 int f[maxn*2];
     13 bool vis[maxn*2];
     14 string str[maxn];
     15 string ans;
     16 inline int to(char ch)
     17 {
     18     if(ch=='A')
     19         return 0;
     20     else if(ch=='C')
     21         return 1;
     22     else if(ch=='G')
     23         return 2;
     24     return 3;
     25 }
     26 inline char back(int x)
     27 {
     28     if(x==0)
     29         return 'A';
     30     else if(x==1)
     31         return 'C';
     32     else if(x==2)
     33         return 'G';
     34     return 'T';
     35 }
     36 struct node
     37 {
     38     int len,fa,ch[4];
     39 };
     40 struct SAM
     41 {
     42     node t[maxn*2];
     43     int last;
     44     inline void insert(int x)
     45     {
     46         int now=++tot,u=last;
     47         last=tot;
     48         t[now].len=t[u].len+1;
     49         for(;u&&!t[u].ch[x];u=t[u].fa)
     50             t[u].ch[x]=now;
     51         if(!u)
     52             t[now].fa=root;
     53         else
     54         {
     55             int v=t[u].ch[x];
     56             if(t[v].len==t[u].len+1)
     57                 t[now].fa=v;
     58             else
     59             {
     60                 int w=++tot;
     61                 t[w]=t[v];
     62                 t[w].len=t[u].len+1;
     63                 t[v].fa=t[now].fa=w;
     64                 for(;u&&t[u].ch[x]==v;u=t[u].fa)
     65                     t[u].ch[x]=w;
     66             }
     67         }
     68     }
     69     inline ll calc()
     70     {
     71         memset(vis,0,sizeof(vis));
     72         for(int i=1;i<=tot;++i)
     73             for(int j=0;j<4;++j)
     74             {
     75                 if(!t[i].ch[j])
     76                     continue;
     77                 ++in[t[i].ch[j]];
     78                 vis[t[i].ch[j]]=1;
     79             }
     80         queue<int>Q;
     81         for(int i=1;i<=tot;++i)
     82             if(!vis[i])
     83                 Q.push(i);
     84         int cnt=0;
     85         while(!Q.empty())
     86         {
     87             int u=Q.front();
     88             Q.pop();
     89             GG[++cnt]=u;
     90             for(int i=0;i<4;++i)
     91             {
     92                 int v=t[u].ch[i];
     93                 if(!v)
     94                     continue;
     95                 --in[v];
     96                 if(!in[v])
     97                     Q.push(v);
     98             }
     99         }
    100         ll sum=0;
    101         for(int i=cnt;i>=1;--i)
    102         {
    103             int u=GG[i];
    104             f[u]=1;
    105             for(int j=0;j<4;++j)
    106             {
    107                 int v=t[u].ch[j];
    108                 if(!v)
    109                     continue;
    110                 f[u]=(f[u]+f[v])%mod;
    111             }
    112         }
    113         return f[root];
    114     }
    115     void out(int u)
    116     {
    117         cout<<ans<<endl;
    118         for(int i=0;i<4;++i)
    119             if(t[u].ch[i])
    120             {
    121                 ans+=back(i);
    122                 out(t[u].ch[i]);
    123                 ans.pop_back();
    124             }
    125     }
    126     void com(int u)
    127     {
    128         if(!vis[u])
    129             wait[++size]=u;
    130         else
    131             return;
    132         vis[u]=1;
    133         for(int i=0;i<4;++i)
    134             if(t[u].ch[i])
    135                 com(t[u].ch[i]);
    136     }
    137     
    138 }S;
    139 int main()
    140 {
    141     ios::sync_with_stdio(false);
    142     cin>>n;
    143     for(int i=1;i<=n;++i)
    144         cin>>str[i];
    145     int last=0,now=0;
    146     for(int G=n;G>=1;--G)
    147     { 
    148         root=S.last=now=++tot;
    149         for(int i=0;i<str[G].size();++i)
    150             S.insert(to(str[G][i]));
    151         if(G!=n)
    152         {
    153             size=0;
    154             S.com(now);
    155             for(int i=1;i<=size;++i)
    156             {
    157                 int u=wait[i];
    158                 for(int j=0;j<4;++j)
    159                     if(!S.t[u].ch[j]&&S.t[last].ch[j])
    160                         S.t[u].ch[j]=S.t[last].ch[j];
    161             }
    162         }
    163         last=now;
    164     }
    165     cin>>k;
    166     if(k==0)
    167         cout<<S.calc()<<endl;
    168     else
    169     {
    170         S.out(now);
    171         cout<<S.calc()<<endl;
    172     }
    173     return 0;
    174 }
    View Code
  • 相关阅读:
    make dep
    TS流的解析
    qt ISO C++ forbids declaration of 'XXXX' with no type
    qt 中文乱码
    qt creator 快捷键 (一)
    qt 坐标变换
    Qt常用类及类方法简介之 QAction类
    QWidget背景(透明)问题
    如何在 QWidget 窗口上弹出右键菜单
    qt 事件
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/11553620.html
Copyright © 2011-2022 走看看