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

 

 

 

posted @ 2013-08-07 13:34  Rabbit_hair  阅读(411)  评论(0)    收藏  举报