您的位置:首页 > 其它

017 ACM/ICPC Asia Regional Shenyang Online 1001 后缀数组+单调队列

2017-09-13 11:57 232 查看



string string string

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2052    Accepted Submission(s): 302


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 (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.

 

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

1.所有子串,考虑后缀数组解
2.画出后缀数组
aabaaab
  aaab
2aab
3aabaaab
1ab
2abaaab
0b
1baaab
3.观察,设某个子串下标为[i],考虑 如果重复K次 那么该序列存在 k-1个子串的最小值为x,即min(height[i],height[i+1]...height[i+k-2]); 设两端点最大值为 y=max(height[i-1],height[i+k-1]),那么对于这K个子串,恰好重复k次的子串为 mex(i,i+y+1),mex(i,i+y+2)...mex(i,i+y+x);
4.维护 x值 ,即为rmq问题,可以采用线段树,st,树状数组等算法,这里可以考虑单调队列,实现简单且O(n)算法。

下面贴出代码

#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
#define maxn 101000
using namespace std;
typedef long long ll;
int wa[maxn],wb[maxn],wv[maxn],wss[maxn];
int r[maxn*3],sa[maxn*3],height[maxn],ranks[maxn];

int c0(int *r,int a,int b)
{
return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
}
int c12(int k,int *r,int a,int b)
{
if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
else return r[a]<r[b]||r[a]==r[b]&&wv[a+1]<wv[b+1];
}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i=0;i<n;i++) wv[i]=r[a[i]];
for(i=0;i<m;i++) wss[i]=0;
for(i=0;i<n;i++) wss[wv[i]]++;
for(i=1;i<m;i++) wss[i]+=wss[i-1];
for(i=n-1;i>=0;i--) b[--wss[wv[i]]]=a[i];
return;
}
void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
r
=r[n+1]=0;
for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
sort(r+2,wa,wb,tbc,m);
sort(r+1,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
if(p<tbc) dc3(rn,san,tbc,p);
else for(i=0;i<tbc;i++) san[rn[i]]=i;
for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
if(n%3==1) wb[ta++]=n-1;
sort(r,wb,wa,ta,m);
for(i=0;i<tbc;i++) wv[wb[i]=G(san[i])]=i;
for(i=0,j=0,p=0;i<ta && j<tbc;p++)
sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
for(;i<ta;p++) sa[p]=wa[i++];
for(;j<tbc;p++) sa[p]=wb[j++];
return;
}
void calheight(int *r,int *sa,int n)
{
memset(ranks,0,sizeof(ranks));
int i,j,k=0;
for(i=1;i<=n;i++) ranks[sa[i]]=i;
for(i=0;i<n;height[ranks[i++]]=k)
for(k?k--:0,j=sa[ranks[i]-1];r[i+k]==r[j+k];k++);
return;
}
char s[maxn];
struct node{
int x;
int index;
node(){
}
node(int x,int index){
this->x=x;
this->index=index;
}
};
deque <node> q;
int ans[maxn];
ll slove(int k,int n){
q.clear();
memset(ans,0,sizeof(ans));
if(k!=1){
for(int i = 2 ; i<=k ; i++){
while(!q.empty()&&height[i]<=q.back().x){
q.pop_back();
}
q.push_back(node(height[i],i));
}
ans[2]=q.front().x;
for(int i = k+1 ; i<=n ; i++){
while(!q.empty()&&height[i]<=q.back().x){
q.pop_back();
}
q.push_back(node(height[i],i));
while(q.front().index<=(i-k+1)){
q.pop_front();
}
ans[i-k+2]=q.front().x;
}
ll num=0;
for(int i = 2 ; i<=n-k+2 ; i++){
int b=height[i+k-1];
if(i+k-1>n){
b=0;
}
int c=max(height[i-1],b);
if(ans[i]>c){
num+=(ans[i]-c);
}
}
return num;
}
else{
ll num=0;
for(int i = 1 ; i<=n ; i++){
ans[i]=n-sa[i];
}
for(int i = 1 ; i<=n ; i++){
int a=height[i];
int b=height[i+1];
if(i==n){
b=0;
}
if(ans[i]-max(a,b)>0)
num+=(ans[i]-max(a,b));
}
return num;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
int k;
scanf("%d",&k);
scanf("%s",s); m
int len=strlen(s);
memset(sa,0,sizeof(sa));
memset(r,0,sizeof(r));
for(int i = 0 ; s[i] ; i++){
r[i]=s[i];

}
dc3(r,sa,len+1,256);
calheight(r,sa,len);
printf("%lld\n",slove(k,len));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐