[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\n",dfsa(1));
92     }
93     return 0;
94 }

 

posted @ 2017-09-14 18:19  skylee03  阅读(127)  评论(0编辑  收藏  举报