zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",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
  • 相关阅读:
    python远程执行dos命令
    python调用cmd显示中文乱码及调用cmd命令
    centos密码策略
    windows密码策略
    windows注册表解析说明
    Acwing-252-树(点分治)
    Gym-10071A-Queries(树状数组)
    2019ICPC沈阳网络赛-B-Dudu's maze(缩点)
    2019ICPC沈阳网络赛-D-Fish eating fruit(树上DP, 换根, 点分治)
    平衡树
  • 原文地址:https://www.cnblogs.com/Rlemon/p/3242938.html
Copyright © 2011-2022 走看看