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 }

 

posted @ 2016-08-06 00:04  Helica  阅读(159)  评论(0编辑  收藏  举报