1. 程式人生 > >HDU 3518 Boring counting(字尾陣列入門題)

HDU 3518 Boring counting(字尾陣列入門題)

Boring counting

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2617    Accepted Submission(s): 1062


Problem Description 035 now faced a tough problem,his english teacher gives him a string,which consists with n lower case letter,he must figure out how many substrings appear at least twice,moreover,such apearances can not overlap each other.
Take aaaa as an example.”a” apears four times,”aa” apears two times without overlaping.however,aaa can’t apear more than one time without overlaping.since we can get “aaa” from [0-2](The position of string begins with 0) and [1-3]. But the interval [0-2] and [1-3] overlaps each other.So “aaa” can not take into account.Therefore,the answer is 2(“a”,and “aa”).

Input The input data consist with several test cases.The input ends with a line “#”.each test case contain a string consists with lower letter,the length n won’t exceed 1000(n <= 1000).
Output For each test case output an integer ans,which represent the answer for the test case.you’d better use int64 to avoid unnecessary trouble.
Sample Input aaaa ababcabb aaaaaa #
Sample Output 2 3 3 題意:求至少出現兩次的不重疊子串的數目總和。字尾陣列入門,但是我不會告訴你我wa了多少次。注意的地方寫在程式碼裡。

AC程式碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
int wa[200005],wb[200005],wv[200005],ws[200005];
int r[200005],height[200005],rank1[200005],sa[200005];
int cmp(int *r,int a,int b,int l){
    return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int *r,int *sa,int n,int m){
    int i,j,p,*x=wa,*y=wb,*t;
    for(i=0;i<m;i++) ws[i]=0;
    for(i=0;i<n;i++) ws[x[i]=r[i]]++;
    for(i=1;i<m;i++) ws[i]+=ws[i-1];
    for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
    for(j=1,p=1;p<n;j*=2,m=p){
        for(p=0,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<n;i++) wv[i]=x[y[i]];
        for(i=0;i<m;i++) ws[i]=0;
        for(i=0;i<n;i++) ws[wv[i]]++;
        for(i=1;i<m;i++) ws[i]+=ws[i-1];
        for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    }
    return;
}
void calheight(int *r,int *sa,int n){
    int i,j,k=0;
    for(i=1;i<=n;i++) rank1[sa[i]]=i;
    for(i=0;i<n;height[rank1[i++]]=k)
        for(k?k--:0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++);
    return;
}
int main()
{
    int i,j,len;char s[1100];
    while(scanf("%s",s)!=EOF&&s[0]!='#')
    {
       len=strlen(s);
       for(i=0;i<len;i++)
       r[i]=s[i];
       r[len]=0;
       da(r,sa,len+1,300);
       calheight(r,sa,len);
       int Max,Min,ans=0;
       for(i=1;i<=len;i++)
       {
         Max=sa[1],Min=sa[1];
         for(j=2;j<=len;j++)
         {
            if(height[j]>=i)
            {
              Max=max(Max,max(sa[j-1],sa[j]));
              Min=min(Min,min(sa[j-1],sa[j]));
            }
            else
            {
              if(Max-Min>=i) ans++;
              Max=sa[j],Min=sa[j];
            }
         }
        if(Max-Min>=i) ans++;//可能從來沒有進入過else裡面,因此要加一個判斷。

       }
       printf("%d\n",ans);
    }
}


相關推薦

HDU 3518 Boring counting字尾陣列入門

Boring counting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2617    Accep

[HDU]3518——Boring counting

break ble tin col figure take in fine each face zhan.jiang.ou now faced a tough problem,his english teacher quan.hong.chun gives him a st

HDU 4358 Boring counting線段樹

用C++交會棧溢位,而G++不會。 更新和查詢我用的是線段樹,1500+ms,用樹狀陣列應該會快一些。 將樹形結構轉換成線性結構後,等價於求指定區間內恰好出現k次的數有多少個。 #include <iostream> #include <cstring&

hdu 5008 字尾陣列 + rmq +二分

題意:給出一個字串,求出第k小的子串,並求出字串的起止位置,如果有多個重複的子串,求出位置最靠左的子串。 思路:比賽時,想到了要用字尾陣列,但是沒想到如何做。 其實,因為子串是字尾的字首,字尾陣列對字尾排序的同時,也對子串進行了排序。對於

hdu 5008 Boring String Problem 字尾陣列

給出一個字串,對於每次的k,求所有子串(去除重複後的)中排名為k的L和R,其中如果有多組解,輸出L最小的。 字尾陣列處理過後,sum[i]表示 sa[1] 到 sa[i] 一共有多少個非重複字串,在sum陣列中二分求出k的lower_bound=pos,那麼第一次出現這個子

2018.11.30 spoj220 Relevant Phrases of Annihilation字尾陣列+二分答案

傳送門 程式碼: 先用特殊字元把所有字串連線在一起。 然後二分答案將 s a sa

2018.11.28 poj3294 Life Forms字尾陣列+雙指標

傳送門 字尾陣列經典題目。 我們先把所有的字串都接在一起。 然後求出 h t ht

2018.11.24 poj3415Common Substrings字尾陣列+單調棧

傳送門 常數實在壓不下來(蒟蒻開O(3)都過不了)。 但有正確性233. 首先肯定得把兩個字串接在一起。 相當於 h e

Newcoder 139 I.Substring字尾陣列+組合數學

Description 兩個字串u1...uku1...uk和v1...vlv1...vl是同構的當且僅當k=lk=l且存在一個單射gg使得ui=g(vi),1≤i≤kui=g(vi),1≤i≤k.

18.12.10 POJ 3450 Corporate Identity字尾陣列+二分法

描述 Beside other services, ACM helps companies to clearly state their “corporate identity”, which includes company logo but also other signs, like trademar

poj2406 Power String字尾陣列DC3/kmp

題意 問該串是最短迴圈節重複了幾次而形成的串,輸出這個次數。 題解 ①kmp顯然可做,求len-next[len]即迴圈節的長度,然後判斷是否能被len整除即可。 ②字尾陣列:列舉迴圈節長度i,i從1到len/2,如果長度為i,則迴圈節顯然為0-(i-1)的子串 先

Power String poj2406字尾陣列+DC3演算法

這題其實應該不是用字尾陣列做的。。。但是就當做練習吧。 倍增演算法在這裡會被卡掉,所以要用DC3演算法。。這裡我是套模板的。。 重點就在於,怎麼找這個迴圈節。 做法是把height陣列出來之後,列舉一下長度。 設長度為i,如果滿足條件的話。 字尾0(整

Luogu4770 NOI2018你的名字字尾陣列+線段樹

  即求b串有多少個本質不同的非空子串,在a串的給定區間內未出現。即使已經8102年並且馬上就9102年了,還是要高舉SA偉大旗幟不動搖。   考慮離線,將所有詢問串及一開始給的串加分隔符連起來,求出SA。對於每個詢問,我們對串的每個字尾,求出其在給定區間中最長的lcp是多少。這樣就能得到不考慮本質不同時的

poj2774字尾陣列||字串hash

求兩個串的最長公共子串 將兩個串連起來,求字尾陣列,sa中相鄰兩個字尾如果不屬於同一個模版,則用這個height更新答案,他們的最長公共字首更新答案 #include<cstdio> #include<cstring> #include<cs

bzoj千計劃312:bzoj2119: 股市的預測字尾陣列+st表

#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #d

bzoj千計劃317:bzoj4650: [Noi2016]優秀的拆分字尾陣列+差分

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 30002 using namespace std; int n;

[BZOJ4516][Sdoi2016]生成魔咒字尾陣列+連結串列

題目 傳送門 題解 這道題還是比較好的; 要求出每一個字首本質不同的字尾的個數,那麼我們可以把原序列倒過來,然後實際上就是對於每一個字尾求與其它字尾不重複的字首個數,也即是字尾長度減去height值; 求出某一個字尾對答案的貢獻之後,他不應該停留在

HDU 2222 Keywords SearchAC自動機模板

stack uil empty cst keywords cto ble ont max http://acm.hdu.edu.cn/showproblem.php?pid=2222 題意:給出多個單詞,最後再給出一個模式串,求在該模式串中包含了多少個單詞。 思路

2016女生賽 HDU 5710 Digit-Sum數學,思維

accep ger sizeof memory fin left total src view Digit-Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Oth

HDU 2544 最短路dijkstra演算法模板

  Problem Description 在每年的校賽裡,所有進入決賽的同學都會獲得一件很漂亮的t-shirt。但是每當我們的工作人員把上百件的衣服從商店運回到賽場的時候,卻是非常累的!所以現在他們想要尋找最短的從商店到賽場的路線,你可以幫助他們嗎?