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.
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 (T≤100) implying the number of test cases.
For each test case, there are two lines:
the first line contains an integer k (k≥1) which is described above;
the second line contain a string s (length(s)≤105).
It's guaranteed that ∑length(s)≤2∗106.
For each test case, there are two lines:
the first line contains an integer k (k≥1) which is described above;
the second line contain a string s (length(s)≤105).
It's guaranteed that ∑length(s)≤2∗106.
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 }
作者:weeping
出处:www.cnblogs.com/weeping/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。