HDU5769-Substring-多校#4-1006-后缀数组
给定一个字符x和一个字符串。要求输出包含此字符的所有不同字串。
后缀数组可以计算一个字符串的所有不同字串,理解了原理就能做这题了。
对于每一个后缀i,将产生len-sa[i]-hight[i]的前缀,累加起来就是所有不同字串。这里要求字串必须包含x
也就是对于每一个后缀i,要减去不含x的前缀。
保存每一个x的位置,用lower_bound查询在此后缀中的第一个x,然后之前的都不计算到贡献当中。
dc3敲起来太慢了
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #define LL long long 5 //using namespace std; 6 7 const int maxn = 1e5+100; 8 #define F(x) ((x)/3+((x)%3 == 1?0:tb)) 9 #define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2) 10 int wa[maxn*3],wb[maxn*3],wv[maxn*3],wss[maxn*3]; 11 12 int c0(int *r,int a,int b) 13 { 14 return r[a] == r[b] && r[a+1] == r[b+1] && r[a+2] == r[b+2]; 15 } 16 int c12(int k,int *r,int a,int b) 17 { 18 if(k == 2) 19 return r[a] < r[b] ||(r[a] == r[b] && c12(1,r,a+1,b+1)); 20 else 21 return r[a] < r[b] ||(r[a] == r[b] && wv[a+1] < wv[b+1]); 22 } 23 void sort(int *r,int *a,int *b,int n,int m) 24 { 25 int i; 26 for(i=0;i<n;i++) wv[i] = r[a[i]]; 27 for(i=0;i<m;i++) wss[i] = 0; 28 for(i=0;i<n;i++) wss[wv[i]]++; 29 for(i=1;i<m;i++) wss[i] += wss[i-1]; 30 for(i=n-1;i>=0;i--)b[--wss[wv[i]] ] = a[i]; 31 } 32 void dc3(int *r,int *_sa,int n,int m) 33 { 34 int i,j,*rn = r+n; 35 int *san = _sa+n,ta = 0,tb=(n+1)/3,tbc=0,p; 36 r[n] = r[n+1] = 0; 37 for(i=0;i<n;i++) if(i%3 != 0) wa[tbc++] = i; 38 sort(r+2,wa,wb,tbc,m); 39 sort(r+1,wb,wa,tbc,m); 40 sort(r,wa,wb,tbc,m); 41 for(p=1,rn[F(wb[0])] = 0,i=1;i<tbc;i++) 42 rn[F(wb[i])] = c0(r,wb[i-1],wb[i]) ? p-1:p++; 43 if(p < tbc) dc3(rn,san,tbc,p); 44 else for(i=0;i<tbc;i++) san[rn[i]] = i; 45 for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++] = san[i]*3; 46 if(n%3==1) wb[ta++] = n-1; 47 sort(r,wb,wa,ta,m); 48 for(i=0;i<tbc;i++) wv[wb[i]=G(san[i]) ] = i; 49 for(i=0,j=0,p=0;i<ta&&j<tbc;p++) 50 _sa[p] = c12(wb[j]%3,r,wa[i],wb[j]) ? wa[i++]:wb[j++]; 51 for(;i<ta;p++) _sa[p] = wa[i++]; 52 for(;j<tbc;p++) _sa[p] = wb[j++]; 53 } 54 void da(int str[],int _sa[],int _rank[],int _height[],int n,int m) 55 { 56 for(int i=n;i<n*3;i++) str[i] = 0; 57 dc3(str,_sa,n+1,m); 58 int i,j,k = 0; 59 for(i=1;i<=n;i++) _rank[_sa[i]] = i; 60 for(i=0;i<n;i++) 61 { 62 if(k) k--; 63 j = _sa[_rank[i]-1 ]; 64 while(str[i+k] == str[j+k]) k++; 65 _height[_rank[i]] = k; 66 } 67 } 68 69 int T; 70 int sa[3*maxn],hehe[3*maxn],rank[maxn],height[maxn]; 71 int x; 72 char line[3*maxn]; 73 74 void debug(int n) 75 { 76 for(int i=0;i<=n;i++) 77 { 78 printf("sa:%d rank:%d height:%d\n",sa[i],rank[i],height[i]); 79 } 80 } 81 82 int main() 83 { 84 //freopen("input.txt","r",stdin); 85 scanf("%d ",&T); 86 int cas = 0; 87 while(T--) 88 { 89 scanf(" %c %s",&x,line); 90 int len = strlen(line); 91 for(int i=0;i<len;i++) hehe[i] = line[i]; 92 int ch[maxn],cnt = 0; 93 for(int i=0;i<len;i++) 94 { 95 if(line[i] == x) ch[cnt++] = i; 96 } 97 ch[cnt++] = len; 98 da(hehe,sa,rank,height,len,300); 99 //debug(len); 100 LL ans = 0; 101 for(int i=1;i<=len;i++) 102 { 103 int pos = ch[std::lower_bound(ch,ch+cnt,sa[i]) - ch] - sa[i]; 104 ans += len -sa[i] ; 105 ans -= std::max(pos,height[i]); 106 } 107 printf("Case #%d: %I64d\n",++cas,ans); 108 } 109 }