给出一个字符串S[1..n],和一个整数k,现在需要求出在S中,对于所有长度为k的子串(k<n),可能不重叠出现的最大次数,如字符串:
 
aacaacbbcbbcbbc
k = 3
 
  其中aac不重叠出现次数为2,bbc不重叠出现的次数为3,则答案是3。
  如果没有重复出现两次及两次以上的不重叠子串,输出0。

 

Input

  第一行:一个整数k
  第二行:一个字符串S,仅包含小写字母,字符串的长度不超过100000

 

Output

  一个整数表示答案。

 

Sample Input

2
abcabdab

 

Sample Output

3

 

Source

xiaoze && zfy0701 @ XMU & CSU stringology invitation 

 

按长度k对height分组,然后贪心同一个分组里面的子串,求同一个分组中最多有几个长度为k的子串是不重叠的,最后求出的最大不重叠数为解。

代码
#include <iostream>
#include 
<cstring>
#include 
<cstdio>
#include 
<climits>
#define MAX  100010
using namespace std;
struct node
{
    
int st,ed;
};
bool cmp(node a,node b)
{
    
if (a.ed == b.ed)
    {
        
return a.st < b.st;
    }
    
return a.ed < b.ed;
}
int mem[4][MAX];
int *sa;
int *rank;
int *nsa;
int *nrank;
int height[MAX];
int cnt[MAX];
int n,k;
char s[MAX];

node edges[MAX
*2];

void make_sa()
{
    sa 
= mem[0];
    rank 
= mem[1];
    nsa 
= mem[2];
    nrank 
= mem[3];

    memset(cnt,
0,sizeof(cnt));
    
for (int i=0;i<n;i++)
    {
        
++cnt[(int)s[i]];
    }
    
for (int i=1;i<256;i++)
    {
        cnt[i]
+=cnt[i-1];
    }
    
for (int i=n-1;i>=0;i--)
    {
        sa[
--cnt[(int)s[i]]] = i;
    }
    rank[sa[
0]] = 0;
    
for (int i=1;i<n;i++)
    {
        rank[sa[i]] 
= rank[sa[i-1]];
        
if (s[sa[i]]!=s[sa[i-1]])
        {
            
++rank[sa[i]];
        }
    }
    
for (int k=1;k<n&&rank[sa[n-1]]<n-1;k*=2)
    {
        
for (int i=0;i<n;i++)
        {
            cnt[rank[sa[i]]] 
= i+1;
        }
        
for (int i=n-1;i>=0;i--)
        {
            
if (sa[i]-k>=0)
            {
                nsa[
--cnt[rank[sa[i]-k]]] = sa[i] - k;
            }
        }
        
for (int i=n-k;i<n;i++)
        {
            nsa[
--cnt[rank[i]]] = i;
        }
        nrank[nsa[
0]] = 0;
        
for (int i=1;i<n;i++)
        {
            nrank[nsa[i]] 
= nrank[nsa[i-1]];
            
if (rank[nsa[i]]!=rank[nsa[i-1]]||rank[nsa[i]+k]!=rank[nsa[i-1]+k])
            {
                
++nrank[nsa[i]];
            }
        }
        swap(rank,nrank);
        swap(sa,nsa);
    }
}
void get_lcp_rmq()
{
    
int i,j,k;
    
for (i=0,k=0;i<n;i++)
    {
        
if (rank[i]==0)
        {
            height[
0= k = 0;
        }
        
else
        {
            
if (k>0)
            {
                k
--;
            }
            j 
= sa[rank[i]-1];
            
for (;s[i+k]==s[j+k];k++);
            height[rank[i]] 
= k;
        }
    }
}

int solve(int len)
{
    
int ans = 1;
    
int kcnt;
    
for (int i=1;i<n;i++)
    {
        
bool flag = false;
        kcnt 
= 0;
        
while (i<n&&height[i]>=len)
        {
            flag 
= true;
            edges[kcnt].st 
= sa[i-1];
            edges[kcnt
++].ed = sa[i-1]+len-1;
            edges[kcnt].st 
= sa[i];
            edges[kcnt
++].ed = sa[i]+len-1;
            i
++;

        }
        sort(edges,edges
+kcnt,cmp);
        
int tans = 1;
        
int mark = edges[0].ed;
        
for (int j=1;j<kcnt;j++)
        {
            
if (edges[j].st>mark)
            {
                tans
++;
                mark 
= edges[j].ed;
            }
        }
        
if(tans>ans)
        {
            ans 
= tans;
        }
        
if (flag)
        {
            i
--;
        }
    }
    
if (ans<2)
    {
        
return 0;
    }
    
return ans;
}
int main()
{
    scanf(
"%d",&k);
    scanf(
"%s",s);
    n 
= strlen(s);
    s[n
++= 0;
    make_sa();
    get_lcp_rmq();
    printf(
"%d\n",solve(k));

    
return 0;
}