zoukankan      html  css  js  c++  java
  • [HDU5343]MZL's Circle Zhou

    题目大意:
      给你两个字符串a和b,从中分别取出子串x和y,求不同的x+y的个数。

    思路:
      对于每一个字符串,构建SAM。
      为了保证相同的x+y不会被重复统计,我们可以想办法只统计相同的x+y中x最长的一种情况。
      考虑在SAM上DP。
      用DFS对a的SAM进行遍历,若当前遍历到的串x不能加上字符c时,在b的SAM中寻找以c开头的y,显然对于这样的x+y,x一定是最长的。
      然后用G++交到HDU上发现TLE了。
      觉得是自己DFS哪里死循环了,未果。
      感觉是被卡常数,用C++交了一发,WA。
      觉得自己的DP可能写的有问题,还是未果。
      估算最后答案的范围,感觉会爆int,就改成了long long。
      又交了一发还是WA。
      随便找了一个题解看看,发现要用unsigned long long,然后就A了。
      这时候再用G++交,不仅A了,而且跑得比C++还快。
      结论:HDU的G++有毒!

     1 #include<cstdio>
     2 #include<cstring>
     3 const int LEN=90001;
     4 char s[LEN];
     5 const int SIGMA_SIZE=26;
     6 struct SuffixAutomaton {
     7     int idx(const char ch) {
     8         return ch-'a';
     9     }
    10     struct State {
    11         int link,go[SIGMA_SIZE],len;
    12     };
    13     State s[LEN<<1];
    14     int len;
    15     int sz,newState(const int l) {
    16         sz++;
    17         s[sz].len=l;
    18         return sz;
    19     }
    20     int root,last;
    21     void extend(const char ch) {
    22         const int w=idx(ch);
    23         int p=last,new_p=newState(s[last].len+1);
    24         while(p&&!s[p].go[w]) {
    25             s[p].go[w]=new_p;
    26             p=s[p].link;
    27         }
    28         if(!p) {
    29             s[new_p].link=root;
    30         } else {
    31             int q=s[p].go[w];
    32             if(s[q].len==s[p].len+1) {
    33                 s[new_p].link=q;
    34             } else {
    35                 int new_q=newState(s[p].len+1);
    36                 memcpy(s[new_q].go,s[q].go,sizeof s[q].go);
    37                 s[new_q].link=s[q].link;
    38                 s[q].link=s[new_p].link=new_q;
    39                 while(p&&s[p].go[w]==q) {
    40                     s[p].go[w]=new_q;
    41                     p=s[p].link;
    42                 }
    43             }
    44         }
    45         last=new_p;
    46     }
    47     void build(char str[]) {
    48         len=strlen(str);
    49         sz=0;
    50         memset(s,0,sizeof s);
    51         root=last=newState(0);
    52         for(int i=0;str[i];i++) extend(str[i]);
    53     }
    54 };
    55 SuffixAutomaton sama,samb;
    56 unsigned long long fa[LEN<<1],fb[LEN<<1];
    57 unsigned long long dfsb(const int x) {
    58     if(~fb[x]) return fb[x];
    59     fb[x]=1;
    60     for(int i=0;i<SIGMA_SIZE;i++) {
    61         if(samb.s[x].go[i]) {
    62             fb[x]+=dfsb(samb.s[x].go[i]);
    63         }
    64     }
    65     return fb[x];
    66 }
    67 unsigned long long dfsa(const int x) {
    68     if(~fa[x]) return fa[x];
    69     fa[x]=1;
    70     for(int i=0;i<SIGMA_SIZE;i++) {
    71         if(sama.s[x].go[i]) {
    72             fa[x]+=dfsa(sama.s[x].go[i]);
    73         } else {
    74             if(samb.s[1].go[i]) {
    75                 fa[x]+=dfsb(samb.s[1].go[i]);
    76             }
    77         }
    78     }
    79     return fa[x];
    80 }
    81 int main() {
    82     int T;
    83     scanf("%d",&T);
    84     while(T--) {
    85         scanf("%s",s);
    86         sama.build(s);
    87         scanf("%s",s);
    88         samb.build(s);
    89         memset(fa,-1,sizeof fa);
    90         memset(fb,-1,sizeof fb);
    91         printf("%llu
    ",dfsa(1));
    92     }
    93     return 0;
    94 }
  • 相关阅读:
    IBM X3650 M4服务器安装centos找不到硬盘的解决方法
    页面头部title、description、keywords标签的优化
    SEO优化之Title 和 Meta 标签
    WPA字典锦集
    PIN码计算锦集
    神经网络入门 第6章 识别手写字体
    神经网络入门 第5章 实现多层神经网络BP算法
    神经网络入门 第4章 神经网络可以模拟任意函数
    神经网络入门 第3章 S函数
    神经网络入门 第2章 编写第一个神经元
  • 原文地址:https://www.cnblogs.com/skylee03/p/7522088.html
Copyright © 2011-2022 走看看