hdu6194 string string string

地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6194

题目:

string string string

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 486    Accepted Submission(s): 125


Problem Description
Uncle Mao is a wonderful ACMER. One day he met an easy problem, but Uncle Mao was so lazy that he left the problem to you. I hope you can give him a solution.
Given a string s, we define a substring that happens exactly k times as an important string, and you need to find out how many substrings which are important strings.
 

 

Input
The first line contains an integer T (T100) implying the number of test cases.
For each test case, there are two lines:
the first line contains an integer k (k1) which is described above;
the second line contain a string s (length(s)105).
It's guaranteed that length(s)2106.
 

 

Output
For each test case, print the number of the important substrings in a line.
 

 

Sample Input
2 2 abcabc 3 abcabcabcabc
 

 

Sample Output
6 9
 

 

Source
   
思路:
  sam会卡指针版的代码,不明白卡这么点内存有什么意思。
  后缀自动机做法:建立sam后,统计出cnt数组,这一步要拓扑排序后倒着dp。
  后缀数组做法:用f[i][j]表示height(i,j)的区间最小值,然后滑动大小为k的窗口,则贡献是max(0,f[i][j]-max(height[i-1],height[j+1]) )
后缀自动机做法:
 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 char ss[100004];
 6 int ans;
 7 
 8 struct SAM
 9 {
10     static const int MAXN = 100001<<1;//大小为字符串长度两倍
11     static const int LetterSize = 26;
12 
13     int tot, last, ch[MAXN][LetterSize], fa[MAXN], len[MAXN];
14     int sum[MAXN], tp[MAXN], cnt[MAXN]; //sum,tp用于拓扑排序,tp为排序后的数组
15 
16     void init( void)
17     {
18         last = tot = 1;
19         len[1] = 0;
20         memset(ch,0,sizeof ch);
21         memset(fa,0,sizeof fa);
22         memset(cnt,0,sizeof cnt);
23     }
24 
25     void add( int x)
26     {
27         int p = last, np = last = ++tot;
28         len[np] = len[p] + 1, cnt[last] = 1;
29         while( p && !ch[p][x]) ch[p][x] = np, p = fa[p];
30         if( p == 0)
31             fa[np] = 1;
32         else
33         {
34             int q = ch[p][x];
35             if( len[q] == len[p] + 1)
36                 fa[np] = q;
37             else
38             {
39                 int nq = ++tot;
40                 memcpy( ch[nq], ch[q], sizeof ch[q]);
41                 len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq;
42                 while( p && ch[p][x] == q)  ch[p][x] = nq, p = fa[p];
43             }
44         }
45     }
46 
47     void toposort( void)
48     {
49         for(int i = 1; i <= len[last]; i++)   sum[i] = 0;
50         for(int i = 1; i <= tot; i++)   sum[len[i]]++;
51         for(int i = 1; i <= len[last]; i++)   sum[i] += sum[i-1];
52         for(int i = 1; i <= tot; i++)   tp[sum[len[i]]--] = i;
53     }
54 } sam;
55 
56 
57 int main(void)
58 {
59     //freopen("in.acm","r",stdin);
60     int t,k;cin>>t;
61     while(t--)
62     {
63         ans=0;
64         sam.init();
65         scanf("%d%s",&k,ss);
66         for(int i=0,len=strlen(ss);i<len;i++)  sam.add(ss[i]-'a');
67         sam.toposort();
68         for(int i=sam.tot;i;i--)
69         {
70             int p=sam.tp[i],fp=sam.fa[p];
71             sam.cnt[fp]+=sam.cnt[p];
72             if(sam.cnt[p]==k)
73                 ans+=sam.len[p]-sam.len[fp];
74         }
75         printf("%d\n",ans);
76     }
77 
78     return 0;
79 }

后缀数组做法:

 1 #include <cstdlib>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #include <set>
 6 #include <iostream>
 7 const int N = 200005;
 8 int sa[N],s[N],wa[N], wb[N], ws[N], wv[N];
 9 int rank[N], height[N];
10 char ss[N];
11 bool cmp(int r[], int a, int b, int l)
12 {
13     return r[a] == r[b] && r[a+l] == r[b+l];
14 }
15 
16 void da(int r[], int sa[], int n, int m)
17 {
18     int i, j, p, *x = wa, *y = wb;
19     for (i = 0; i < m; ++i) ws[i] = 0;
20     for (i = 0; i < n; ++i) ws[x[i]=r[i]]++;
21     for (i = 1; i < m; ++i) ws[i] += ws[i-1];
22     for (i = n-1; i >= 0; --i) sa[--ws[x[i]]] = i;
23     for (j = 1, p = 1; p < n; j *= 2, m = p)
24     {
25         for (p = 0, i = n - j; i < n; ++i) y[p++] = i;
26         for (i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
27         for (i = 0; i < n; ++i) wv[i] = x[y[i]];
28         for (i = 0; i < m; ++i) ws[i] = 0;
29         for (i = 0; i < n; ++i) ws[wv[i]]++;
30         for (i = 1; i < m; ++i) ws[i] += ws[i-1];
31         for (i = n-1; i >= 0; --i) sa[--ws[wv[i]]] = y[i];
32         for (std::swap(x, y), p = 1, x[sa[0]] = 0, i = 1; i < n; ++i)
33             x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++;
34     }
35 }
36 
37 void calheight(int r[], int sa[], int n)
38 {
39     int i, j, k = 0;
40     for (i = 1; i <= n; ++i) rank[sa[i]] = i;
41     for (i = 0; i < n; height[rank[i++]] = k)
42         for (k?k--:0, j = sa[rank[i]-1]; r[i+k] == r[j+k]; k++);
43 }
44 struct RMQ
45 {
46     int log2[N],mi[N][25];
47     void init(int n)
48     {
49         for(int i = 0; i <= n; i ++)log2[i] = (i == 0 ? -1 : log2[i >> 1] + 1);
50         for(int j = 1; j < log2[n]; j ++)
51             for(int i = 1; i + (1 << j) <= n + 1; i ++)
52                 mi[i][j] = std::min(mi[i][j - 1], mi[i + (1 << j - 1)][j - 1]);
53     }
54     int query(int ql, int qr)
55     {
56         int k = log2[qr - ql + 1];
57         return std::min(mi[ql][k], mi[qr - (1 << k) + 1][k]);
58     }
59 } rmq;
60 int sc(int i,int k,int len)
61 {
62     if(k==1) return len-sa[i];
63     return rmq.query(i+1,i+k-1);
64 }
65 int main()
66 {
67     int t,k;std::cin>>t;
68     while(t--)
69     {
70         int ans=0;
71         scanf("%d%s",&k,ss);
72         int len=strlen(ss);
73         for(int i=0;i<len;i++)
74             s[i]=ss[i]-'a'+1;
75         s[len]=0;
76         da(s,sa,len+1,28);
77         calheight(s,sa,len);
78         height[len+1]=0;
79         for(int i=1;i<=len;i++)
80             rmq.mi[i][0]=height[i];
81         rmq.init(len);
82         for(int i=1;i<=len-k+1;i++)
83             ans+=std::max(sc(i,k,len)-std::max(height[i],height[i+k]),0);
84         printf("%d\n",ans);
85     }
86     return 0;
87 }

 

posted @ 2017-09-11 11:02  weeping  阅读(1067)  评论(0编辑  收藏  举报