(后缀数组)HDU 6194-string string string
Posted 惜取少年时
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(后缀数组)HDU 6194-string string string相关的知识,希望对你有一定的参考价值。
string string string
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 774 Accepted Submission(s): 225
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
只需求出出现次数>=k和 >=k+1的个数。
对于求出现次数>=x的,如果x=1,则直接特判输出。
若不然,只需维护长度x-1的height序列(height序列长度x-1 则对应的后缀数即为x),维护序列中height的最小值,按下标从小到大扫,注意到每次更新,只有该最小值发生变大时,才会增加新的出现次数>=x次的子串。(不变或变小时当前的子串之前都计数过)
以此计算>=x >=x+1的相减即可。
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <vector> 5 #include <set> 6 #include <map> 7 #include <string> 8 #include <cstring> 9 #include <stack> 10 #include <queue> 11 #include <cmath> 12 #include <ctime> 13 #include <bitset> 14 #include <utility> 15 #include <assert.h> 16 using namespace std; 17 #define rank rankk 18 #define mp make_pair 19 #define pb push_back 20 #define xo(a,b) ((b)&1?(a):0) 21 #define tm tmp 22 //#define LL ll 23 typedef unsigned long long ull; 24 typedef pair<int,int> pii; 25 typedef long long ll; 26 typedef pair<ll,int> pli; 27 typedef pair<ll,ll> pll; 28 const int INF=0x3f3f3f3f; 29 const ll INFF=0x3f3f3f3f3f3f3f3fll; 30 const int MAX=1e5+5; 31 //const ll MAXN=2e8; 32 const int MAX_N=MAX; 33 const ll MOD=998244353; 34 //const long double pi=acos(-1.0); 35 //const double eps=0.00000001; 36 int gcd(int a,int b){return b?gcd(b,a%b):a;} 37 template<typename T>inline T abs(T a) {return a>0?a:-a;} 38 template<class T> inline 39 void read(T& num) { 40 bool start=false,neg=false; 41 char c; 42 num=0; 43 while((c=getchar())!=EOF) { 44 if(c==‘-‘) start=neg=true; 45 else if(c>=‘0‘ && c<=‘9‘) { 46 start=true; 47 num=num*10+c-‘0‘; 48 } else if(start) break; 49 } 50 if(neg) num=-num; 51 } 52 inline ll powMM(ll a,ll b,ll M){ 53 ll ret=1; 54 a%=M; 55 // b%=M; 56 while (b){ 57 if (b&1) ret=ret*a%M; 58 b>>=1; 59 a=a*a%M; 60 } 61 return ret; 62 } 63 void open() 64 { 65 // freopen("1009.in","r",stdin); 66 freopen("out.txt","w",stdout); 67 } 68 const int MAXN=100005; 69 int t1[MAXN],t2[MAXN],c[MAXN];//求SA数组需要的中间变量,不需要赋值 70 //待排序的字符串放在s数组中,从s[0]到s[n-1],长度为n,且最大值小于m, 71 //除s[n-1]外的所有s[i]都大于0,r[n-1]=0 72 //函数结束以后结果放在sa数组中 73 bool cmp(int *r,int a,int b,int l) 74 { 75 return r[a] == r[b] && r[a+l] == r[b+l]; 76 } 77 void da(int str[],int sa[],int rank[],int height[],int n,int m) 78 { 79 str[n++]=0; 80 int i, j, p, *x = t1, *y = t2; 81 //第一轮基数排序,如果s的最大值很大,可改为快速排序 82 for(i = 0;i < m;i++)c[i] = 0; 83 for(i = 0;i < n;i++)c[x[i] = str[i]]++; 84 for(i = 1;i < m;i++)c[i] += c[i-1]; 85 for(i = n-1;i >= 0;i--)sa[--c[x[i]]] = i; 86 for(j = 1;j <= n; j <<= 1) 87 { 88 p = 0; 89 //直接利用sa数组排序第二关键字 90 for(i = n-j; i < n; i++)y[p++] = i;//后面的j个数第二关键字为空的最小 91 for(i = 0; i < n; i++)if(sa[i] >= j)y[p++] = sa[i] - j; 92 //这样数组y保存的就是按照第二关键字排序的结果 93 //基数排序第一关键字 94 for(i = 0; i < m; i++)c[i] = 0; 95 for(i = 0; i < n; i++)c[x[y[i]]]++; 96 for(i = 1; i < m;i++)c[i] += c[i-1]; 97 for(i = n-1; i >= 0;i--)sa[--c[x[y[i]]]] = y[i]; 98 swap(x,y); 99 //根据sa和x数组计算新的x数组 swap(x,y); 100 p = 1; x[sa[0]] = 0; 101 for(i = 1;i < n;i++) 102 x[sa[i]] = cmp(y,sa[i-1],sa[i],j)?p-1:p++; 103 if(p >= n)break; 104 m = p;//下次基数排序的最大值 105 } 106 int k = 0; n--; 107 for(i = 0;i <= n;i++)rank[sa[i]] = i; 108 for(i = 0;i < n;i++) 109 { 110 if(k)k--; 111 j = sa[rank[i]-1]; while(str[i+k] == str[j+k])k++; height[rank[i]] = k; 112 } 113 } 114 int rank[MAXN],height[MAXN]; 115 int RMQ[MAXN]; 116 int mm[MAXN]; 117 int best[20][MAXN]; 118 void initRMQ(int n) 119 { 120 mm[0]=-1; 121 for(int i=1;i<=n;i++) 122 mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1]; 123 for(int i=1;i<=n;i++)best[0][i]=i; 124 for(int i=1;i<=mm[n];i++) 125 for(int j=1;j+(1<<i)-1<=n;j++) 126 { 127 int a=best[i-1][j]; 128 int b=best[i-1][j+(1<<(i-1))]; 129 if(RMQ[a]<RMQ[b])best[i][j]=a; else best[i][j]=b; 130 } 131 } 132 int askRMQ(int a,int b) 133 { 134 int t; t=mm[b-a+1]; 135 b-=(1<<t)-1; 136 a=best[t][a];b=best[t][b]; 137 return RMQ[a]<RMQ[b]?a:b; 138 } 139 int lcp(int a,int b) 140 { 141 a=rank[a];b=rank[b]; 142 if(a>b)swap(a,b); 143 return height[askRMQ(a+1,b)]; 144 } 145 int t,k,len; 146 char sts[MAXN]; 147 int st[MAXN],sa[MAXN]; 148 multiset<int>s; 149 ll cal(int x) 150 { 151 ll an=0; 152 if(x==1) 153 { 154 an=1LL*len*(len+1LL)/2LL; 155 for(int i=1;i<=len;i++)an-=height[i]; 156 } 157 else 158 { 159 s.clear(); 160 for(int i=1;i<=x-1;i++)s.insert(height[i]); 161 for(int i=x;i<=len;i++) 162 { 163 int pre=*s.begin();s.erase(s.find(height[i-x+1]));s.insert(height[i]); 164 printf("%d %d!\n",pre,*s.begin()); 165 an+=max(0,*s.begin()-pre); 166 } 167 } 168 return an; 169 } 170 int main() 171 { 172 scanf("%d",&t); 173 while(t--) 174 { 175 scanf("%d",&k); 176 scanf("%s",sts);len=strlen(sts); 177 memset(height,0,sizeof(height)); 178 for(int i=0;i<len;i++)st[i]=sts[i]-‘a‘+1; 179 da(st,sa,rank,height,len,27); 180 for(int i=1;i<=len;i++) 181 printf("%d\n",height[i]); 182 printf("%lld\n",cal(k)-cal(k+1)); 183 } 184 }
以上是关于(后缀数组)HDU 6194-string string string的主要内容,如果未能解决你的问题,请参考以下文章
hdu-6194 string string string 后缀数组 出现恰好K次的串的数量
HDU 6194 string string string(后缀自动机)
后缀数组RMQHDU 6194 - string string string (2017ICPC沈阳网络赛)