HDU 6194 string string string

題目鏈接:HDU 6194

string string string

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


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
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:  6205 6204 6203 6202 6201 
 

題意:給出一個字符串,問其中恰好出現k次的不同子串有多少個。

題目分析:詢問不同子串個數那基本就是後綴數組沒跑了,這裏將所有的子串按排名列出來,可以看出,排名連續的子串的公共前綴一定出現了至少k次。之後我們的工作就是判斷這裏有多找個前綴出現次數比k次多,然後分別排名往前和往後看一位,如果還有公共前綴就把這些前綴去掉,height數組保存的就是牌名相鄰的2個串公共前綴,我們是滑動大小爲k的窗口並維護最小值,可以單調棧可以RMQ,不過後綴數組模板自帶RMQ,調整下RMQ查詢即可。

細節問題:

我的模板height[i]保存的是排名i與排名i-1的公共前綴,所以要注意查詢範圍。

rank數組從1開始,height數組也是從1開始。

RMQ模板傳的2個參數是左右邊界在實際字符串的位置,所以對於排名i需要傳sa[i]。

對於K=1的情況不特判會RE(RE-1),實際上k=1相當於窗口大小爲1,那麼公共前綴就是自己的長度,其他相同,不需要添油加醋(WA-2)TAT。

PS:對於第9題,我們隊一早就發現了這個bug,然後有一段時間忙着寫題沒管,然後等卡題了於是我們閒着無聊就二進制從1開始挨個試着交,然後交了200多次竟然過了。。。然後吃瓜羣衆看到我們原來還有這種操作,就開始也暴力提交,,,於是boom!!!真是打得最歡樂的一場網絡賽了,整個比賽節奏都被我們帶歪了。。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int K;
const int maxn=200010;
int t1[maxn],t2[maxn],c[maxn];
bool cmp(int *r,int a,int b,int l)
{
    return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int str[],int sa[],int ranks[],int height[],int n,int m)
{
    n++;
    int i,j,p,*x=t1,*y=t2;
    for(i=0;i<m;i++) c[i]=0;
    for(i=0;i<n;i++) c[x[i]=str[i]]++;
    for(i=1;i<m;i++) c[i]+=c[i-1];
    for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
    for(j=1;j<=n;j<<=1)
    {
        p=0;
        for(i=n-j;i<n;i++) y[p++]=i;
        for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
        for(i=0;i<m;i++) c[i]=0;
        for(i=0;i<n;i++) c[x[y[i]]]++;
        for(i=1;i<m;i++) c[i]+=c[i-1];
        for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;x[sa[0]]=0;
        for(i=1;i<n;i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
        if(p>=n) break;
        m=p;
    }
    int k=0;
    n--;
    for(i=0;i<=n;i++)ranks[sa[i]]=i;
    for(i=0;i<n;i++)
    {
        if(k)k--;
        j=sa[ranks[i]-1];
        while(str[i+k]==str[j+k])k++;
        height[ranks[i]]=k;
    }
}
int ranks[maxn],height[maxn];
char str[maxn];
int r[maxn],sa[maxn];
int pre[maxn],vis[maxn];
int RMQ[maxn],mm[maxn];
int dp[maxn][60];

void Rmq_Init(int n)
{
    int m=floor(log(n+0.0)/log(2.0));
    for(int i=1;i<=n;i++) dp[i][0]=height[i];
    for(int i=1;i<=m;i++)
    {
        for(int j=n;j;j--){
            dp[j][i]=dp[j][i-1];
            if(j+(1<<(i-1))<=n)
                dp[j][i]=min(dp[j][i],dp[j+(1<<(i-1))][i-1]);
        }
    }
}
int Rmq_Query(int l,int r)
{
    int a=ranks[l],b=ranks[r];
    if(a>b) swap(a,b);
    a++;
    int m=floor(log(b-a+1.0)/log(2.0));
    return min(dp[a][m],dp[b-(1<<m)+1][m]);
}



int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&K);
        scanf("%s",str);
        int len=strlen(str);
        for(int i=0;i<len;i++) r[i]=str[i];
        r[len]=0;
        da(r,sa,ranks,height,len,128);
        Rmq_Init(len);
        long long int ans=0;
        for(int i=1;i+K-1<=len;i++)
        {
            int buf2=0,buf3=0,buf1=0;
            int a1=sa[i],a2=sa[i+K-1];
            if(K!=1) buf1=Rmq_Query(a1, a2);
            else buf1=len-sa[i];
            if(i!=0) buf2=height[i];
            if(i+K-1<len) buf3=height[i+K];
                if(buf2>buf1||buf3>buf1) continue;
                else
                {
                    ans+=buf1-max(buf3,buf2);
                }
        }
        printf("%lld\n",ans);
    }
}


發佈了168 篇原創文章 · 獲贊 4 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章