题目大意:
给你两个字符串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 }