hdu 4029
题意:给你一个字符矩阵,统计不同的子矩阵的个数;
分析:枚举子矩阵的宽度w,对于每一个w,将每一行长度可以是w的字符串HASH成一个值,然后用map标记,因为宽确定了,hash完之后,然后如果相等就表示此时长度为w的字串
相等,将他们按照每一列排序形成一个字符串,此时如果莫两个长度为x的子串相等就表示此时x*w的子矩阵相同,
这样就是统计m个字符串的不同的子串的个数,这个是SA的论文题;n^3*logn
HASH会冲突,SEED选择很重要,当然也可以用2个SEED,这样冲突的概率就很小很小了;
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<cstdlib> 7 #include<map> 8 #define mk make_pair 9 10 using namespace std; 11 typedef unsigned long long ULL; 12 typedef pair<ULL,ULL> pUU; 13 const int N = 50000+10; 14 const int M = 200+10; 15 const int SEED[2]= {13,11}; 16 char s[M][M]; 17 ULL hash[2][M][M],X[2][M]; 18 int n,m; 19 map<pUU,int> mp; 20 int str[N]; 21 struct Suffix_Array { 22 int a1[N],a2[N],c[N],sa[N],SA[N],*x,*y,n,m; 23 int height[N],*rank; 24 void sort(){ 25 for (int i = 0; i < m; i++) c[i] = 0; 26 for (int i = 0; i < n; i++) c[ x[i] ] ++; 27 for (int i = 0; i < m; i++) c[i+1] += c[i]; 28 for (int i = n-1; i >= 0; i--) SA[ --c[x[sa[i]]] ] = sa[i]; 29 } 30 void build_SA(int s[],int _n,int _m) { 31 n = _n; m = _m; 32 x = a1; y = a2; x[n] = y[n] = -1; 33 for (int i = 0; i < n; i++) x[i] = s[i], sa[i] = i; 34 sort(); 35 for (int k = 1; k <= n; k <<= 1) { 36 int p = 0; 37 for (int i = n-k; i < n; i++) sa[ p++ ] = i; 38 for (int i = 0; i < n; i++) if (SA[i] >= k) sa[ p++ ] = SA[i] - k; 39 sort(); 40 p = 0; y[SA[0]] = 0; 41 for (int i = 1; i < n; i++) { 42 if ( x[SA[i-1]] != x[SA[i]] || x[SA[i-1]+k] != x[SA[i]+k] ) p++; 43 y[SA[i]] = p; 44 } 45 swap(x,y); 46 if (p+1 == n) break; 47 m = p + 1; 48 } 49 rank = x; getHeight(s); 50 } 51 void getHeight(int s[]){ 52 int k = 0; 53 for (int i = 0; i < n; i++) { 54 if (k) k--; 55 if (rank[i] == 0) continue; 56 int j = SA[rank[i] - 1]; 57 while ( s[j+k] && s[i+k] == s[j+k]) k++; 58 height[ rank[i] ] = k; 59 } 60 height[n] = 0; 61 } 62 void check(){ 63 for (int i = 0; i < n; i++) cout<<SA[i]<<" "; cout<<endl; 64 for (int i = 0; i < n; i++) cout<<rank[i]<<" "; cout<<endl; 65 for (int i = 0; i < n; i++) cout<<height[i]<<" "; cout<<endl; 66 } 67 }H; 68 69 void init(){ 70 // 会用到的一定要清空; 71 for (int k = 0; k < 2; k++) 72 for (int i = 0; i < n; i++) { 73 hash[k][i][m] = 0;//会用到,如果不清空会wa; 74 hash[k][i][m-1] = s[i][m-1] - 'A'; 75 for (int j = m-2; j >= 0; j--) { 76 hash[k][i][j] = hash[k][i][j+1] * SEED[k] + s[i][j] - 'A'; 77 } 78 } 79 X[0][0] = X[1][0] = 1; 80 for (int k = 0; k < 2; k++) 81 for (int i = 1; i <= m; i++) { 82 X[k][i] = X[k][i-1] * SEED[k]; 83 } 84 } 85 86 int idx[N]; 87 int find(int n){ 88 int ret = idx[H.SA[0]]; 89 for (int i = 1; i < n; i++){ 90 ret += idx[H.SA[i]] - H.height[i]; 91 } 92 return ret; 93 } 94 void solve(){ 95 int ret = 0; 96 int cnt, tot; 97 for (int w = 1; w <= m; w++) { 98 cnt = 0, tot = 1; 99 mp.clear(); 100 for (int j = 0; j+w-1 < m; j++){ 101 for (int i = 0; i < n; i++) { 102 ULL tmp1 = hash[0][i][j] - hash[0][i][j+w] * X[0][w]; 103 ULL tmp2 = hash[1][i][j] - hash[1][i][j+w] * X[1][w]; 104 105 if (mp.find(mk(tmp1,tmp2)) == mp.end()){ 106 mp[mk(tmp1,tmp2)] = tot++; 107 } 108 idx[cnt] = n - i; 109 str[cnt++] = mp[mk(tmp1,tmp2)]; 110 } 111 idx[cnt] = 0; 112 str[cnt++] = tot++; 113 } 114 H.build_SA(str,cnt,tot); 115 // H.check(); 116 ret += find(cnt); 117 } 118 printf("%d\n",ret); 119 120 } 121 int main(){ 122 int T, cas = 0; scanf("%d",&T); 123 while (T--){ 124 scanf("%d%d",&n,&m); 125 for (int i = 0; i < n; i++) { 126 scanf("%s",s[i]); 127 } 128 init(); 129 printf("Case #%d: ",++cas); 130 solve(); 131 } 132 return 0; 133 }
UVA 10829
题意:给你一个串,求形如UVU的子串的个数,其中v的长度为g;
思路:枚举u的长度i,将串每i个字符一组,如:
bbaabaaa i == 2
bb | aa | ba | aa
01 2 3 4 5 6 7
1 #include<cstdlib> 2 #include<cstdio> 3 #include<iostream> 4 #include<cmath> 5 #include<vector> 6 #include<cstring> 7 #include<algorithm> 8 #include<queue> 9 using namespace std; 10 const int N = 50000+10; 11 struct SA{ 12 int a1[N],a2[N],c[N],sa[N],SA[N],*x,*y,n,m; 13 int height[N],*rank; 14 int f[20][N]; 15 void sort() { 16 for (int i = 0; i < m; i++) c[i] = 0; 17 for (int i = 0; i < n; i++) c[ x[i] ] ++; 18 for (int i = 0; i < m; i++) c[i+1] += c[i]; 19 for (int i = n-1; i >= 0; i--) 20 SA[ --c[x[sa[i]]] ] = sa[i]; 21 } 22 void build_SA(char *s,int _n,int _m){ 23 n = _n; m = _m; 24 x = a1; y = a2; x[n] = y[n] = -1; 25 for (int i = 0; i < n; i++) x[i] = s[i], sa[i] = i; 26 sort(); 27 for (int k = 1; k <= n; k <<= 1) { 28 int p = 0; 29 for (int i = n-k; i < n; i++) sa[p++] = i; 30 for (int i = 0; i < n; i++) if (SA[i] >= k) sa[p++] = SA[i] - k; 31 sort(); 32 p = 0; y[SA[0]] = 0; 33 for (int i = 1; i < n; i++) { 34 if (x[SA[i-1]] != x[SA[i]] || x[SA[i-1]+k] != x[SA[i]+k] ) p++; 35 y[SA[i]] = p; 36 } 37 swap(x,y); 38 if (p+1 == n) break; 39 m = p+1; 40 } 41 rank = x; getHeight(s); 42 } 43 void getHeight(char *s) { 44 int k = 0; 45 for (int i = 0; i < n; i++) { 46 if (k) k--; 47 if (rank[i] == 0) continue; 48 int j = SA[rank[i]-1]; 49 while (i + k < n && j + k < n && s[i+k] == s[j+k]) k++; 50 height[ rank[i] ] = k; 51 } 52 height[n] = 0; 53 } 54 void initRMQ(){ 55 for (int i = 1; i < n; i++) f[0][i] = height[i]; 56 for (int i = 1; (1<<i) < n; i++) { 57 for (int j = 1; j+(1<<i)-1 < n; j++) { 58 f[i][j] = min(f[i-1][j], f[i-1][j+(1<<i>>1)]); 59 } 60 } 61 } 62 int lcp(int a,int b) { 63 a = rank[a]; b = rank[b]; 64 if (a > b) swap(a,b); 65 a++; 66 int t = 0; 67 while ((1<<t) <= (b - a + 1)) t++; 68 t--; 69 return min(f[t][a], f[t][b - (1<<t) + 1]); 70 } 71 void check(){ 72 // build_SA("aabaab",6,220); 73 for (int i = 0; i < n; i++) { 74 cout<<SA[i]<<" "; 75 }cout<<endl; 76 for (int i = 0; i < n; i++) { 77 cout<<rank[i]<<" "; 78 }cout<<endl; 79 for (int i = 1; i < n; i++) { 80 cout<<height[i]<<" "; 81 }cout<<endl; 82 } 83 }H1,H2; 84 int g; 85 void solve(){ 86 int ret = 0; 87 int len =strlen(s); 88 for (int i = 0; i < len; i++) { 89 s2[i] = s[len - i - 1]; 90 } 91 H1.build_SA(s,len,255); 92 H2.build_SA(s2,len,255); 93 H1.initRMQ(); H2.initRMQ(); 94 for (int i = 1; i <= (len - g)/2; i++) { 95 for (int j = 0; j + i + g < len; j += i) { 96 int l = j, r = j + i + g; 97 int u, v, w = 0; 98 u = H1.lcp(l,r); v = H2.lcp(len - 1 - l,len - 1 - r); 99 // cout<<" **** "<<i<<endl; 100 // cout<<l<<" "<<r<<endl; 101 // cout<<u<<" "<<v<<endl; 102 if (v <= i) w = v; 103 else w = 1; 104 if (u <= 2*i -1) w += u; 105 else w += 2*i - 1; 106 ret += max(0,w-i); 107 //cout<<w<<" "<<ret<<endl; 108 } 109 } 110 printf("%d\n",ret); 111 } 112 int main(){ 113 // H.check(); 114 int T, cas = 0; scanf("%d",&T); 115 while (T--) { 116 scanf("%d%s",&g,s); 117 printf("Case %d: ",++cas); 118 solve(); 119 120 } 121 return 0; 122 }
poj 3415
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<vector> 5 #include<iostream> 6 #include<algorithm> 7 #include<cmath> 8 using namespace std; 9 typedef long long LL; 10 const int N = 2*100000+10; 11 struct Point{ 12 int val,cnt; 13 Point(){} 14 Point(int x,int y):val(x),cnt(y){} 15 }; 16 int k; 17 struct dequeue{ 18 int head,tail; 19 Point q[N]; 20 void init(){ 21 head = 1; tail = 0; 22 } 23 void push(Point pp,LL &sum){ 24 while (head <= tail && pp.val <= q[tail].val) { 25 sum -= (LL)(q[tail].val - k + 1) * q[tail].cnt; 26 pp.cnt += q[tail].cnt; 27 tail--; 28 } 29 sum += (LL)(pp.val - k + 1) * pp.cnt; 30 q[++tail] = pp; 31 } 32 }R; 33 34 struct SA{ 35 int a1[N],a2[N],c[N],sa[N],SA[N],*x,*y,n,m; 36 int height[N],*rank; 37 void sort(){ 38 for (int i = 0; i < m; i++) c[i] = 0; 39 for (int i = 0; i < n; i++) c[ x[i] ]++; 40 for (int i = 0; i < m; i++) c[i+1] += c[i]; 41 for (int i = n-1; i >= 0; i--) 42 SA[ --c[x[sa[i]]] ] = sa[i]; 43 } 44 void build_SA(char *s,int _n,int _m){ 45 n = _n; m = _m; 46 x = a1; y = a2; x[n] = y[n] = -1; 47 for (int i = 0; i < n; i++) x[i] = s[i], sa[i] = i; 48 sort(); 49 for (int k = 1; k <= n; k <<= 1) { 50 int p = 0; 51 for (int i = n-k; i < n; i++) sa[ p++ ] = i; 52 for (int i = 0; i < n; i++) if (SA[i] >= k) sa[ p++ ] = SA[i] - k; 53 sort(); 54 p = 0; y[SA[0]] = 0; 55 for (int i = 1; i < n; i++) { 56 if ( x[SA[i-1]] != x[SA[i]] || x[SA[i-1]+k] != x[SA[i]+k] ) p++; 57 y[SA[i]] = p; 58 } 59 swap(x,y); 60 if (p+1 == n) break; 61 m = p + 1; 62 } 63 rank = x; getHeight(s); 64 } 65 void getHeight(char *s) { 66 int k = 0; 67 for (int i = 0; i < n; i++) { 68 if (k) k--; 69 if (rank[i] == 0) continue; 70 int j = SA[rank[i] - 1]; 71 while (s[i+k] == s[j+k] && i+k < n && j+k < n) k++; 72 height[ rank[i] ] =k; 73 } 74 height[n] = 0; 75 } 76 int idx(int x,int mid) { 77 if (x < mid) return 1; 78 return 0; 79 } 80 LL solve(int limt,int mid,int tar){//tar in queue 81 R.init(); 82 LL ret = 0; 83 LL sum = 0; 84 for (int i = 1; i <= n; i++) { 85 if (height[i] >= limt){ 86 // cout<<SA[i-1]<<" "; 87 if (idx(SA[i-1],mid) == tar) { 88 R.push(Point(height[i],1),sum); 89 }else { 90 ret += sum; 91 R.push(Point(height[i],0),sum); 92 } 93 }else { 94 //cout<<SA[i-1]<<" **** "<<endl; 95 if (idx(SA[i-1],mid) != tar){ 96 ret += sum; 97 } 98 R.init(); 99 sum = 0; 100 } 101 } 102 return ret; 103 } 104 void check(){ 105 // build_SA("aabaab",6,255); 106 for (int i = 0; i < n; i++) cout<<SA[i]<<" ";cout<<endl; 107 for (int i = 0; i < n; i++) cout<<rank[i]<<" ";cout<<endl; 108 for (int i = 1; i < n; i++) cout<<height[i]<<" ";cout<<endl; 109 } 110 }H; 111 int mid,len; 112 char s[N]; 113 void solve(){ 114 LL ret = 0; 115 //H.check(); 116 ret += H.solve(k,mid,0); 117 //cout<<ret<<endl; 118 ret += H.solve(k,mid,1); 119 printf("%lld\n",ret); 120 } 121 int main(){ 122 // H.check(); 123 while (~scanf("%d",&k),k) { 124 scanf("%s",s); 125 mid = strlen(s); 126 s[mid] = '#'; 127 scanf("%s",s+mid+1); 128 len = strlen(s); 129 // cout<<s<<endl; 130 H.build_SA(s,len,255); 131 solve(); 132 } 133 return 0; 134 } 135 /* 136 2 137 aababaa 138 abaabaa 139 1 140 xx 141 xx 142 0 143 */