HDU3518 Boring counting

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

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

Source

2010 ACM-ICPC Multi-University Training Contest(9)——Host by HNU

Recommend

zhengfeng

字符串 后缀数组

求至少不重叠出现2次以上的子串有多少个

建立后缀数组,按height把后缀们分成不同的组,同一组内都是相同的后缀,统计它们出现的最大最小位置即可

 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<vector>
 8 using namespace std;
 9 const int mxn=100010;
10 int read(){
11     int x=0,f=1;char ch=getchar();
12     while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
13     while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
14     return x*f;
15 }
16 int sa[mxn],rk[mxn],ht[mxn];
17 int wa[mxn],wb[mxn],wv[mxn],cnt[mxn];
18 char s[mxn];
19 inline int cmp(int *r,int a,int b,int l){
20     return r[a]==r[b] && r[a+l]==r[b+l];
21 }
22 void GSA(int *sa,int n,int m){
23     int i,j,k;
24     int *x=wa,*y=wb;
25     for(i=0;i<m;i++)cnt[i]=0;
26     for(i=0;i<n;i++)cnt[x[i]=s[i]-‘a‘+1]++;
27     for(i=1;i<m;i++)cnt[i]+=cnt[i-1];
28     for(i=n-1;i>=0;i--)sa[--cnt[x[i]]]=i;
29     for(int p=0,j=1;p<n;j<<=1,m=p){
30         for(p=0,i=n-j;i<n;i++)y[p++]=i;
31         for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
32         for(i=0;i<n;i++)
33             wv[i]=x[y[i]];
34         for(i=0;i<m;i++)cnt[i]=0;
35         for(i=0;i<n;i++)cnt[wv[i]]++;
36         for(i=1;i<m;i++)cnt[i]+=cnt[i-1];
37         for(i=n-1;i>=0;i--)sa[--cnt[wv[i]]]=y[i];
38         swap(x,y);
39         p=1;x[sa[0]]=0;
40         for(i=1;i<n;i++)
41             x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;
42     }
43     return;
44 }
45 void GHT(int n){
46     int i,j,k=0;
47     for(i=1;i<=n;i++)rk[sa[i]]=i;
48     for(i=0;i<n;i++){
49         if(k)k--;
50         j=sa[rk[i]-1];
51         while(s[i+k]==s[j+k])k++;
52         ht[rk[i]]=k;
53     }
54     return;
55 }
56 int ans=0;
57 bool solve(int n,int lim){
58     bool flag=0;
59     int mxpos=-100,mnpos=mxn;
60     for(int i=1;i<=n;i++){
61         if(ht[i]<lim){
62             if(mxpos-mnpos>=lim){
63                 ans++;flag=1;
64             }
65             mxpos=-100,mnpos=mxn;
66         }
67         mxpos=max(mxpos,sa[i]);
68         mnpos=min(mnpos,sa[i]);
69     }
70     if(mxpos-mnpos>=lim)flag=1,ans++;
71     return flag;
72 }
73 int main(){
74     int i,j;
75     while(scanf("%s",s) && s[0]!=‘#‘){
76         int len=strlen(s);
77         s[len]=‘a‘-1;
78         GSA(sa,len+1,28);
79         GHT(len);
80         ans=0;
81 //        for(i=0;i<=len;i++)printf("%c",s[i]);puts("");
82 //        for(i=1;i<=len;i++)printf("%d ",sa[i]);puts("");
83 //        for(i=1;i<=len;i++)printf("%d ",ht[i]);puts("");
84         for(i=1;i<len;i++){
85             if(!solve(len,i))break;
86         }
87         printf("%d\n",ans);
88     }
89     return 0;
90 }
时间: 2024-12-13 21:02:50

HDU3518 Boring counting的相关文章

[HDU3518]Boring counting(后缀数组)

传送门 求出现超过1次的不重叠子串的个数 根据论文中的方法. 枚举子串的长度 k. 用 k 给 height 数组分组,每一组求解,看看当前组的位置最靠后的后缀和位置最靠前的后缀所差个数是否大于长度,大于的话 ans++. 分组思想需要认真体会一下. ——代码 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define N 1005 5 #define max(x, y) ((x) &

hdu3518 Boring Counting[后缀排序]

裸的统计不同的重复出现子串(不重叠)种数的题.多次使用后缀排序要注意小细节.y数组在重复使用时一定要清空,看那个line25 +k就明白了 ,cnt也要清空,为什么就不说了 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;} 5 temp

BNUOJ 7629 Boring counting

Boring counting Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 351864-bit integer IO format: %I64d      Java class name: Main 035 now faced a tough problem,his english teacher gives him a string,which consis

13年山东省赛 Boring Counting(离线树状数组or主席树+二分or划分树+二分)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 2224: Boring Counting Time Limit: 3 Sec  Memory Limit: 128 MB Description In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence.

HDOJ 3518 Boring counting

SAM基本操作 拓扑求每个节点的  最左出现left,最右出现right,出现了几次num ...... 对于每一个出现两次以上的节点,对其所对应的一串子串的长度范围 [fa->len+1,len] 和其最大间距 right-left比较 即可...... Boring counting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s):

UPC 2224 Boring Counting (离线线段树,统计区间[l,r]之间大小在[A,B]中的数的个数)

题目链接:http://acm.upc.edu.cn/problem.php?id=2224 题意:给出n个数pi,和m个查询,每个查询给出l,r,a,b,让你求在区间l~r之间的pi的个数(A<=pi<=B,l<=i<=r). 参考链接:http://www.cnblogs.com/zj62/p/3558967.html #include <iostream> #include <cstdio> #include <cstring> #incl

HDOJ 题目3518 Boring counting(后缀数组,求不重叠重复次数最少为2的子串种类数)

Boring counting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2253    Accepted Submission(s): 924 Problem Description 035 now faced a tough problem,his english teacher gives him a string,whic

后缀数组 --- HDU 3518 Boring counting

Boring counting Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3518 Mean: 给你一个字符串,让你求出有多少个子串(无重叠)至少出现了两次. analyse: 后缀数组中height数组的运用,一般这个数组用得很少. 总体思路:分组统计的思想:将相同前缀的后缀分在一个组,然后对于1到len/2的每一个固定长度进行统计ans. 首先我们先求一遍后缀数组,并把height数组求出来.height数组代表的

hdu 3518 Boring counting(后缀数组)

Boring counting                                                                       Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description 035 now faced a tough problem,his english teacher gives him