SA

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 }
View Code

 

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 }
View Code

 

 

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 */
View Code

 

 

 

你可能感兴趣的:(SA)