后缀数组系列

Musical Theme
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 30544   Accepted: 10208

Description

A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the piano. It is unfortunate but true that this representation of melodies ignores the notion of musical timing; but, this programming task is about notes and not timings. 
Many composers structure their music around a repeating &qout;theme&qout;, which, being a subsequence of an entire melody, is a sequence of integers in our representation. A subsequence of a melody is a theme if it: 
  • is at least five notes long 
  • appears (potentially transposed -- see below) again somewhere else in the piece of music 
  • is disjoint from (i.e., non-overlapping with) at least one of its other appearance(s)

Transposed means that a constant positive or negative value is added to every note value in the theme subsequence. 
Given a melody, compute the length (number of notes) of the longest theme. 
One second time limit for this problem's solutions! 

Input

The input contains several test cases. The first line of each test case contains the integer N. The following n integers represent the sequence of notes. 
The last test case is followed by one zero. 

Output

For each test case, the output file should contain a single line with a single integer that represents the length of the longest theme. If there are no themes, output 0.

Sample Input

30
25 27 30 34 39 45 52 60 69 79 69 60 52 45 39 34 30 26 22 18
82 78 74 70 66 67 64 60 65 80
0

Sample Output

5

论文模板题,求出height后二分答案,在二分的时候按照mid把后缀数组进行分组,每组内的后缀最小公共前缀>=mid。只要有一组内的头位置最大值最小值相差>=mid,说明是存在长度为mid的不重叠子串。
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define clr(x) memset(x,0,sizeof(x))
  6 #define clrmax(x) memset)x,0x3f3f3f3f,sizeof(x))
  7 using namespace std;
  8 const int N=2e4+10;
  9 int ranked[N],order[N],backet[N],s[N],sa[N],key1[N],key2[N],height[N];
 10 int n,m,l,r,mid,T,ans;
 11 //两后缀比较大小
 12 bool cmp(int *r,int a,int b,int len)
 13 {
 14     return r[a]==r[b] && r[a+len]==r[b+len];
 15 }
 16 //求后缀数组sa,r为字符串,order代表按照第二关键字排序后的第一关键字的顺序,x[i]代表i的后缀的rank,y[i]代表第二关键字为i的头位置。order[i]代表按照第二关键字排序完rank为i的后缀对应的第一关键字对应的rank
 17 void da(int *sa,int *r,int n,int m)
 18 {
 19     int i,j,p,*x=key1,*y=key2,*t;
 20     //对长度为1的字符排序
 21     for(i=0;i<m;i++) backet[i]=0;
 22     for(i=0;i<n;i++) backet[x[i]=r[i]]++;
 23     for(i=1;i<m;i++) backet[i]+=backet[i-1];
 24     for(i=n-1;i>=0;i--) sa[--backet[x[i]]]=i;
 25     for(j=1,p=1;p<n;j*=2,m=p)
 26     {
 27         //按第二关键字排序
 28         for(p=0,i=n-j;i<n;i++) y[p++]=i;
 29         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
 30         //以第二关键字排序的结果按照第一关键字排序
 31         for(i=0;i<n;i++) order[i]=x[y[i]];
 32         for(i=0;i<m;i++) backet[i]=0;
 33         for(i=0;i<n;i++) backet[order[i]]++;
 34         for(i=1;i<m;i++) backet[i]+=backet[i-1];
 35         for(i=n-1;i>=0;i--) sa[--backet[order[i]]]=y[i];
 36         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
 37             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
 38     }
 39     return ;
 40 }
 41 //求height数组
 42 void calheight(int *sa,int *r,int n)
 43 {
 44     int i,j,k=0;
 45     //求出sa对应的rank
 46     for(i=1;i<=n;i++) ranked[sa[i]]=i;
 47     //按照h[i]去求height[i]
 48     for(i=0;i<n;i++)
 49     {
 50         if(k) k--;
 51         j=sa[ranked[i]-1];
 52         while(r[i+k]==r[j+k]) k++;
 53         height[ranked[i]]=k;
 54     }
 55     return ;
 56 }
 57 int minn,minpos,maxpos,flag;
 58 int main()
 59 {
 60     while(scanf("%d",&n)!=EOF && n)
 61     {
 62         for(int i=1;i<=n;i++)
 63         {
 64             scanf("%d",&s[i]);
 65         }
 66         for(int i=1;i<n;i++)
 67         {
 68             s[i]=s[i+1]-s[i]+100;
 69         }
 70         s[n]=1;
 71         n--;
 72         da(sa,s+1,n+1,200);
 73         calheight(sa,s+1,n);
 74         l=0;
 75         r=n/2;
 76 //        for(int i=0;i<=n;i++)
 77 //            printf("%d ",sa[i]);
 78 //        printf("
");
 79 //        for(int i=0;i<=n;i++)
 80 //            printf("%d ",ranked[i]);
 81 //        printf("
");
 82 //        for(int i=0;i<=n;i++)
 83 //            printf("%d ",height[i]);
 84 //        printf("
");
 85 //二分答案求值
 86         while(l<=r)
 87         {
 88             mid=(r+l)>>1;
 89             minn=n;
 90             minpos=maxpos=sa[1];
 91             flag=0;
 92             for(int i=2;i<=n;i++)
 93             {
 94                 if(height[i]<mid)
 95                     maxpos=minpos=sa[i];
 96                 else
 97                 {
 98                     maxpos=max(maxpos,sa[i]);
 99                     minpos=min(minpos,sa[i]);
100                     if(maxpos-minpos>=mid)
101                     {
102                         flag=1;
103                         break;
104                     }
105                 }
106             }
107             if(flag)
108                 ans=mid,l=mid+1;
109             else
110                 r=mid-1;
111         }
112         if(ans<4)
113             printf("0
");
114         else
115             printf("%d
",ans+1);
116     }
117     return 0;
118 }
View Code
Milk Patterns
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 16268   Accepted: 7175
Case Time Limit: 2000MS

Description

Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some regular patterns in the daily milk quality.

To perform a rigorous study, he has invented a complex classification scheme by which each milk sample is recorded as an integer between 0 and 1,000,000 inclusive, and has recorded data from a single cow over N (1 ≤ N ≤ 20,000) days. He wishes to find the longest pattern of samples which repeats identically at least K (2 ≤ K ≤ N) times. This may include overlapping patterns -- 1 2 3 2 3 2 3 1 repeats 2 3 2 3 twice, for example.

Help Farmer John by finding the longest repeating subsequence in the sequence of samples. It is guaranteed that at least one subsequence is repeated at least K times.

Input

Line 1: Two space-separated integers: N and K 
Lines 2..N+1: N integers, one per line, the quality of the milk on day i appears on the ith line.

Output

Line 1: One integer, the length of the longest pattern which occurs at least K times

Sample Input

8 2
1
2
3
2
3
2
3
1

Sample Output

4

依旧论文模板题,仍旧二分答案,满足的条件是区间内元素大于等于k。
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define clr(x) memset(x,0,sizeof(x))
  6 #define clrmax(x) memset)x,0x3f3f3f3f,sizeof(x))
  7 using namespace std;
  8 const int N=1e5+10;
  9 int ranked[N],order[N],backet[N],s[N],sa[N],key1[N],key2[N],height[N];
 10 int n,m,ans,k;
 11 int unrep[N];
 12 bool cmp(int *r,int a,int b,int len)
 13 {
 14     return r[a]==r[b] && r[a+len]==r[b+len];
 15 }
 16 void da(int *sa,int *r,int n,int m)
 17 {
 18     int i,j,p,*x=key1,*y=key2,*t;
 19     for(i=0;i<m;i++) backet[i]=0;
 20     for(i=0;i<n;i++) backet[x[i]=r[i]]++;
 21     for(i=1;i<m;i++) backet[i]+=backet[i-1];
 22     for(i=n-1;i>=0;i--) sa[--backet[x[i]]]=i;
 23     for(j=1,p=1;p<n;j*=2,m=p)
 24     {
 25         for(p=0,i=n-j;i<n;i++) y[p++]=i;
 26         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
 27         for(i=0;i<n;i++) order[i]=x[y[i]];
 28         for(i=0;i<m;i++) backet[i]=0;
 29         for(i=0;i<n;i++) backet[order[i]]++;
 30         for(i=1;i<m;i++) backet[i]+=backet[i-1];
 31         for(i=n-1;i>=0;i--) sa[--backet[order[i]]]=y[i];
 32         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
 33             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
 34     }
 35     return ;
 36 }
 37 void calheight(int *sa,int *r,int n)
 38 {
 39     int i,j,k=0;
 40     for(i=1;i<=n;i++) ranked[sa[i]]=i;
 41     for(i=0;i<n;i++)
 42     {
 43         if(k) k--;
 44         j=sa[ranked[i]-1];
 45         while(r[i+k]==r[j+k]) k++;
 46         height[ranked[i]]=k;
 47     }
 48     return ;
 49 }
 50 bool check(int k,int mid,int n,int *heigiht)
 51 {
 52     int ct=1;
 53     for(int i=2;i<=n;i++)
 54     {
 55         if(height[i]<mid)
 56         {
 57             ct=1;
 58         }
 59         else
 60         {
 61             if((++ct)>=k)
 62             {
 63                 return 1;
 64             }
 65         }
 66     }
 67     return 0;
 68 }
 69 void bina(int &ans,int k,int *height,int n)
 70 {
 71     int l=ans=1,r=n,mid;
 72     while(l<=r)
 73     {
 74         mid=(l+r)>>1;
 75         if(check(k,mid,n,height))
 76             ans=mid,l=mid+1;
 77         else
 78             r=mid-1;
 79     }
 80     return ;
 81 }
 82 int main()
 83 {
 84     while(scanf("%d%d",&n,&k)!=EOF)
 85     {
 86         for(int i=1;i<=n;i++)
 87             scanf("%d",&s[i]);
 88         memcpy(unrep,s,sizeof(s));
 89         sort(unrep+1,unrep+n+1);
 90         m=unique(unrep+1,unrep+n+1)-unrep-1;
 91         for(int i=1;i<=n;i++)
 92             s[i]=lower_bound(unrep+1,unrep+m+1,s[i])-unrep;
 93         s[++n]=0;
 94         da(sa,s+1,n,m+10);
 95         n--;
 96         calheight(sa,s+1,n);
 97         bina(ans,k,height,n);
 98         printf("%d
",ans);
 99     }
100     return 0;
101 }
View Code

poj 2406

Power Strings
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 51609   Accepted: 21523

Description

Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = "" (the empty string) and a^(n+1) = a*(a^n).

Input

Each test case is a line of input representing s, a string of printable characters. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.

Output

For each s you should print the largest n such that s = a^n for some string a.

Sample Input

abcd
aaaa
ababab
.

Sample Output

1
4
3

这题用KMP去匹配会更好一点。。但论文里要求了用后缀数组那就用吧~。
这题得用DC3不然时间不太够。然后求每个后缀和0后缀的最长公共前缀(lcp)。然后只要位置k的后缀和0后缀的lcp长度为n-k说明0~k-1这是一个整串的重复子串。我们只要找到最短的一个重复子串,那么就能使得求得的n最大了。
于是height处理完以后,求出各个后缀和0后缀的lcp,从小到大找符合要求的子串长度(n%k==0的长度k是合法的)。求这个lcp是O(1)的。整个算法是O(n)的(DC3的常数会比较大)。
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define clr(x) memset(x,0,sizeof(x))
 6 #define clr_1(x) memset(x,-1,sizeof(x))
 7 #define LL long long
 8 #define mod 1000000007
 9 #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
10 #define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)
11 using namespace std;
12 const int N=3e6+10;
13 int wa[N],wb[N],backet[N],order[N],sa[N];
14 int ranked[N],height[N],s[N],lcp[N],n;
15 char str[N];
16 int c0(int *r,int a,int b)
17 {
18     return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
19 }
20 int c12(int k,int *r,int a,int b)
21 {
22     if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
23     else return r[a]<r[b]||r[a]==r[b]&&order[a+1]<order[b+1];
24 }
25 void sorted(int *r,int *a,int *b,int n,int m)
26 {
27     int i;
28     for(i=0;i<n;i++) order[i]=r[a[i]];
29     for(i=0;i<m;i++) backet[i]=0;
30     for(i=0;i<n;i++) backet[order[i]]++;
31     for(i=1;i<m;i++) backet[i]+=backet[i-1];
32     for(i=n-1;i>=0;i--) b[--backet[order[i]]]=a[i];
33     return;
34 }
35 void dc3(int *r,int *sa,int n,int m)
36 {
37     int i,j,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
38     int *rn=r+n;
39     r[n]=r[n+1]=0;
40     for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
41     sorted(r+2,wa,wb,tbc,m);
42     sorted(r+1,wb,wa,tbc,m);
43     sorted(r,wa,wb,tbc,m);
44     for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
45         rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
46     if(p<tbc) dc3(rn,san,tbc,p);
47     else for(i=0;i<tbc;i++) san[rn[i]]=i;
48     for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
49     if(n%3==1) wb[ta++]=n-1;
50     sorted(r,wb,wa,ta,m);
51     for(i=0;i<tbc;i++) order[wb[i]=G(san[i])]=i;
52     for(i=0,j=0,p=0;i<ta && j<tbc;p++)
53         sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
54     for(;i<ta;p++) sa[p]=wa[i++];
55     for(;j<tbc;p++) sa[p]=wb[j++];
56     return;
57 }
58 void calheight(int *r, int *sa, int n) {
59     int i, j, k = 0;
60     for (i = 1; i <= n; i++) ranked[sa[i]] = i;
61     for (i = 0; i < n; height[ranked[i++]] = k)
62         for (k ? k-- : 0, j = sa[ranked[i] - 1]; r[i + k] == r[j + k]; k++);
63     return ;
64 }
65 
66 int len,m,ans;
67 int main()
68 {
69     while(scanf("%s",str) && str[0]!='.')
70     {
71         len=strlen(str);
72         for(int i=0;i<len;i++)
73             s[i]=str[i]-'a'+1;
74         s[len]=0;
75         dc3(s,sa,len+1,30);
76         calheight(s,sa,len);
77         m=ranked[0];
78         lcp[0]=len;
79         for( int i=2;i<=m;i++)
80             lcp[sa[i-1]]=min(height[i],lcp[sa[i]]);
81         for(int i=m+1;i<=len;i++)
82             lcp[sa[i]]=min(height[i],lcp[sa[i-1]]);
83         for(int i=1;i<=len;i++)
84             if(len%i==0)
85             {
86                 if(lcp[i]==len-i)
87                 {
88                     ans=len/i;
89                     break;
90                 }
91             }
92         printf("%d
",ans);
93     }
94 }
View Code

  

SPOJ SUBST1

SUBST1 - New Distinct Substrings

Given a string, we need to find the total number of its distinct substrings.

Input

T- number of test cases. T<=20; Each test case consists of one string, whose length is <= 50000

Output

For each test case output one number saying the number of distinct substrings.

Example

Input:
2
CCCCC
ABABA

Output:
5
9

论文题,求出height后height0和height(n+1)都作为0,然后求sa上每串和他sa位置相邻的两串中最长的前缀(height),则是这一串里最长(长度为h)的相同子串,把后缀长度减去该子串长度就是该串贡献的不同的子串的个数(即长度为(h+1)~n-sa[i]).
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define clr(x) memset(x,0,sizeof(x))
 6 #define clrmax(x) memset)x,0x3f3f3f3f,sizeof(x))
 7 using namespace std;
 8 const int N=1e5+10;
 9 int ranked[N],order[N],backet[N],sa[N],key1[N],key2[N],height[N];
10 char s[N];
11 int n,m,ans,k;
12 int unrep[N];
13 bool cmp(int *r,int a,int b,int len)
14 {
15     return r[a]==r[b] && r[a+len]==r[b+len];
16 }
17 void da(int *sa,char *r,int n,int m)
18 {
19     int i,j,p,*x=key1,*y=key2,*t;
20     for(i=0;i<m;i++) backet[i]=0;
21     for(i=0;i<n;i++) backet[x[i]=r[i]]++;
22     for(i=1;i<m;i++) backet[i]+=backet[i-1];
23     for(i=n-1;i>=0;i--) sa[--backet[x[i]]]=i;
24     for(j=1,p=1;p<n;j*=2,m=p)
25     {
26         for(p=0,i=n-j;i<n;i++) y[p++]=i;
27         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
28         for(i=0;i<n;i++) order[i]=x[y[i]];
29         for(i=0;i<m;i++) backet[i]=0;
30         for(i=0;i<n;i++) backet[order[i]]++;
31         for(i=1;i<m;i++) backet[i]+=backet[i-1];
32         for(i=n-1;i>=0;i--) sa[--backet[order[i]]]=y[i];
33         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
34             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
35     }
36     return ;
37 }
38 void calheight(int *sa,char *r,int n)
39 {
40     int i,j,k=0;
41     for(i=1;i<=n;i++) ranked[sa[i]]=i;
42     for(i=0;i<n;i++)
43     {
44         if(k) k--;
45         j=sa[ranked[i]-1];
46         while(r[i+k]==r[j+k]) k++;
47         height[ranked[i]]=k;
48     }
49     return ;
50 }
51 int main()
52 {
53     int T;
54     scanf("%d",&T);
55     while(T--)
56     {
57         scanf("%s",s);
58         n=strlen(s);
59         n++;
60         da(sa,s,n,200);
61         n--;
62         calheight(sa,s,n);
63         height[n+1]=height[1]=0;
64         ans=0;
65         for(int i=1;i<=n;i++)
66         {
67             ans+=n-sa[i]-height[i];
68         }
69         printf("%d
",ans);
70     }
71     return 0;
72 }
View Code

 SPOJ - REPEATS 

REPEATS - Repeats

no tags 

A string s is called an (k,l)-repeat if s is obtained by concatenating k>=1 times some seed string t with length l>=1. For example, the string

s = abaabaabaaba

is a (4,3)-repeat with t = aba as its seed string. That is, the seed string t is 3 characters long, and the whole string s is obtained by repeating t 4 times.

Write a program for the following task: Your program is given a long string u consisting of characters ‘a’ and/or ‘b’ as input. Your program must find some (k,l)-repeat that occurs as substring within u with k as large as possible. For example, the input string

u = babbabaabaabaabab

contains the underlined (4,3)-repeat s starting at position 5. Since u contains no other contiguous substring with more than 4 repeats, your program must output the maximum k.

Input

In the first line of the input contains H- the number of test cases (H <= 20). H test cases follow. First line of each test cases is n - length of the input string (n <= 50000), The next n lines contain the input string, one character (either ‘a’ or ‘b’) per line, in order.

Output

For each test cases, you should write exactly one interger k in a line - the repeat count that is maximized.

Example

Input:
1
17
b
a
b
b
a
b
a
a
b
a
a
b
a
a
b
a
b

Output:
4

有两种方法。基础是罗穗骞《后缀数组——处理字符串的有力工具》写的:

然后第一个就是求一遍后缀数组和height,然后写st表来快速求两后缀的最长公共前缀。然后用这个lcp[i][i+l]的长度定位该重复子串头,当前位置为i,那么头位置为tj=i-lcp[i][i+l]%i,然后再求一遍lcp[tj][tj+l],那lcp[tj][tj+l]/l即为其重复次数。

第二种会麻烦点,时间也久一点求后缀数组的lcp,把该字符串倒过来,也求其后缀数组的lcp,相当于求其前缀数组的lcs。然后每次就将i和i+l俩位置的后缀的lcp以及i-1,i+l-1俩位置前缀的lcs相加,除以l+1,即为重复次数。

  1 #include<bits/stdc++.h>
  2 #define clr(x) memset(x,0,sizeof(x))
  3 #define clr_1(x) memset(x,-1,sizeof(x))
  4 #define LL long long
  5 #define mod 1000000007
  6 #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
  7 #define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)
  8 using namespace std;
  9 const int N=1e6+10;
 10 const int M=1e5+10;
 11 int wa[N],wb[N],backet[N],order[N],sal[N];
 12 int rankl[N],heightl[N],sl[N],n;
 13 typedef vector<int> vec;
 14 typedef vector<vec> stable;
 15 stable stl(M,vec(20));
 16 int c0(int *r,int a,int b)
 17 {
 18     return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
 19 }
 20 int c12(int k,int *r,int a,int b)
 21 {
 22     if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
 23     else return r[a]<r[b]||r[a]==r[b]&&order[a+1]<order[b+1];
 24 }
 25 void sorted(int *r,int *a,int *b,int n,int m)
 26 {
 27     int i;
 28     for(i=0;i<n;i++) order[i]=r[a[i]];
 29     for(i=0;i<m;i++) backet[i]=0;
 30     for(i=0;i<n;i++) backet[order[i]]++;
 31     for(i=1;i<m;i++) backet[i]+=backet[i-1];
 32     for(i=n-1;i>=0;i--) b[--backet[order[i]]]=a[i];
 33     return;
 34 }
 35 void dc3(int *r,int *sa,int n,int m)
 36 {
 37     int i,j,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
 38     int *rn=r+n;
 39     r[n]=r[n+1]=0;
 40     for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
 41     sorted(r+2,wa,wb,tbc,m);
 42     sorted(r+1,wb,wa,tbc,m);
 43     sorted(r,wa,wb,tbc,m);
 44     for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
 45         rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
 46     if(p<tbc) dc3(rn,san,tbc,p);
 47     else for(i=0;i<tbc;i++) san[rn[i]]=i;
 48     for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
 49     if(n%3==1) wb[ta++]=n-1;
 50     sorted(r,wb,wa,ta,m);
 51     for(i=0;i<tbc;i++) order[wb[i]=G(san[i])]=i;
 52     for(i=0,j=0,p=0;i<ta && j<tbc;p++)
 53         sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
 54     for(;i<ta;p++) sa[p]=wa[i++];
 55     for(;j<tbc;p++) sa[p]=wb[j++];
 56     return;
 57 }
 58 void calheight(int *r, int *sa, int n,int *height,int *ranked) {
 59     int i, j, k = 0;
 60     for (i = 1; i <= n; i++) ranked[sa[i]] = i;
 61     for (i = 0; i < n; height[ranked[i++]] = k)
 62         for (k ? k-- : 0, j = sa[ranked[i] - 1]; r[i + k] == r[j + k]; k++);
 63     return ;
 64 }
 65 void dealst(int *height,stable &st,int n,int *sa)
 66 {
 67     int t=0,k,divk;
 68     for(int i=1;i<n;i++)
 69         st[i][1]=height[i+1];
 70     for(k=4,t=2,divk=2;k<=n;k<<=1,divk<<=1,t++)
 71         for(int i=1;i<=n-k+1;i++)
 72             st[i][t]=min(min(st[i][t-1],st[i+divk][t-1]),height[i+divk]);
 73     return ;
 74 }
 75 int query(int u,int v,stable &st,int *ranked)
 76 {
 77     u=ranked[u];
 78     v=ranked[v];
 79     if(u>v) swap(u,v);
 80     int p=v-u+1,k=0;
 81     while(p)
 82     {
 83         p>>=1;
 84         k++;
 85     }
 86     return min(st[u][k-1],st[v-(1<<k-1)+1][k-1]);
 87 }
 88 int m,ans,maxn,tj,d;
 89 int main()
 90 {
 91     int T,n,m;
 92     char c;
 93     scanf("%d",&T);
 94     while(T--)
 95     {
 96         scanf("%d",&n);
 97         for(int i=0;i<n;i++)
 98         {
 99             scanf(" %c",&c);
100             sl[i]=c-'a'+1;
101         }
102         if(n==0)
103         {
104             printf("0
");
105             continue;
106         }
107         sl[n++]=0;
108         dc3(sl,sal,n,30);
109         n--;
110         calheight(sl,sal,n,heightl,rankl);
111         dealst(heightl,stl,n,sal);
112         maxn=0;
113         for(int l=1;l<=n/2;l++)
114         {
115             for(int j=0;j<n-l;j+=l)
116             {
117                 d=query(j,j+l,stl,rankl);
118                 ans=d/l;
119                 tj=j-(l-d%l);
120                 if(tj>=0)
121                 {
122                     if(query(tj,tj+l,stl,rankl)>=l-d%l)
123                         ans++;
124                 }
125                 if(maxn<ans)
126                     maxn=ans;
127             }
128         }
129         printf("%d
",maxn+1);
130     }
131     return 0;
132 }
第一种
  1 #include<bits/stdc++.h>
  2 #define clr(x) memset(x,0,sizeof(x))
  3 #define clr_1(x) memset(x,-1,sizeof(x))
  4 #define LL long long
  5 #define mod 1000000007
  6 #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
  7 #define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)
  8 using namespace std;
  9 const int N=1e6+10;
 10 const int M=1e5+10;
 11 int wa[N],wb[N],backet[N],order[N],sap[N],sal[N];
 12 int rankp[N],heightp[N],rankl[N],heightl[N],sp[N],sl[N],n;
 13 typedef vector<int> vec;
 14 typedef vector<vec> stable;
 15 stable stp(M,vec(20)),stl(M,vec(20));
 16 int c0(int *r,int a,int b)
 17 {
 18     return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
 19 }
 20 int c12(int k,int *r,int a,int b)
 21 {
 22     if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
 23     else return r[a]<r[b]||r[a]==r[b]&&order[a+1]<order[b+1];
 24 }
 25 void sorted(int *r,int *a,int *b,int n,int m)
 26 {
 27     int i;
 28     for(i=0;i<n;i++) order[i]=r[a[i]];
 29     for(i=0;i<m;i++) backet[i]=0;
 30     for(i=0;i<n;i++) backet[order[i]]++;
 31     for(i=1;i<m;i++) backet[i]+=backet[i-1];
 32     for(i=n-1;i>=0;i--) b[--backet[order[i]]]=a[i];
 33     return;
 34 }
 35 void dc3(int *r,int *sa,int n,int m)
 36 {
 37     int i,j,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
 38     int *rn=r+n;
 39     r[n]=r[n+1]=0;
 40     for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
 41     sorted(r+2,wa,wb,tbc,m);
 42     sorted(r+1,wb,wa,tbc,m);
 43     sorted(r,wa,wb,tbc,m);
 44     for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
 45         rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
 46     if(p<tbc) dc3(rn,san,tbc,p);
 47     else for(i=0;i<tbc;i++) san[rn[i]]=i;
 48     for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
 49     if(n%3==1) wb[ta++]=n-1;
 50     sorted(r,wb,wa,ta,m);
 51     for(i=0;i<tbc;i++) order[wb[i]=G(san[i])]=i;
 52     for(i=0,j=0,p=0;i<ta && j<tbc;p++)
 53         sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
 54     for(;i<ta;p++) sa[p]=wa[i++];
 55     for(;j<tbc;p++) sa[p]=wb[j++];
 56     return;
 57 }
 58 void calheight(int *r, int *sa, int n,int *height,int *ranked) {
 59     int i, j, k = 0;
 60     for (i = 1; i <= n; i++) ranked[sa[i]] = i;
 61     for (i = 0; i < n; height[ranked[i++]] = k)
 62         for (k ? k-- : 0, j = sa[ranked[i] - 1]; r[i + k] == r[j + k]; k++);
 63     return ;
 64 }
 65 void dealst(int *height,stable &st,int n,int *sa)
 66 {
 67     int t=0,k,divk;
 68     for(int i=1;i<n;i++)
 69         st[i][1]=height[i+1];
 70     for(k=4,t=2,divk=2;k<=n;k<<=1,divk<<=1,t++)
 71         for(int i=1;i<=n-k+1;i++)
 72             st[i][t]=min(min(st[i][t-1],st[i+divk][t-1]),height[i+divk]);
 73     return ;
 74 }
 75 int query(int u,int v,stable &st,int *ranked)
 76 {
 77     u=ranked[u];
 78     v=ranked[v];
 79     if(u>v) swap(u,v);
 80     int p=v-u+1,k=0;
 81     while(p)
 82     {
 83         p>>=1;
 84         k++;
 85     }
 86     return min(st[u][k-1],st[v-(1<<k-1)+1][k-1]);
 87 }
 88 int len,m,ans,maxn;
 89 int main()
 90 {
 91     int T,n,m;
 92     char c;
 93     scanf("%d",&T);
 94     while(T--)
 95     {
 96         scanf("%d",&n);
 97         for(int i=0;i<n;i++)
 98         {
 99             scanf(" %c",&c);
100             sp[n-i-1]=sl[i]=c-'a'+1;
101         }
102         if(n==0)
103         {
104             printf("0
");
105             continue;
106         }
107         sp[n]=0;
108         sl[n++]=0;
109         dc3(sp,sap,n,30);
110         dc3(sl,sal,n,30);
111         n--;
112         calheight(sp,sap,n,heightp,rankp);
113         calheight(sl,sal,n,heightl,rankl);
114         dealst(heightp,stp,n,sap);
115         dealst(heightl,stl,n,sal);
116         maxn=1;
117         for(int l=1;l<=n/2;l++)
118         {
119             for(int j=0;j<n-l;j+=l)
120             {
121                 ans=query(j,j+l,stl,rankl)+query(n-j,n-j-l,stp,rankp);
122                 ans=ans/l+1;
123                 if(ans>maxn)
124                     maxn=ans;
125 
126             }
127         }
128         printf("%d
",maxn);
129     }
130     return 0;
131 }
第二种

poj 3693

Maximum repetition substring
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 10540   Accepted: 3255

Description

The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same consecutive substrings. For example, the repetition number of "ababab" is 3 and "ababa" is 1.

Given a string containing lowercase letters, you are to find a substring of it with maximum repetition number.

Input

The input consists of multiple test cases. Each test case contains exactly one line, which
gives a non-empty string consisting of lowercase letters. The length of the string will not be greater than 100,000.

The last test case is followed by a line containing a '#'.

Output

For each test case, print a line containing the test case number( beginning with 1) followed by the substring of maximum repetition number. If there are multiple substrings of maximum repetition number, print the lexicographically smallest one.

Sample Input

ccabababc
daabbccaa
#

Sample Output

Case 1: ababab
Case 2: aa


  因为内存开大了所以超时了????反正我开100w的数组他不提示mle而是tle。。我开小点就过了。
  跟上题一样,由于每次都要查询符合条件位置及其前l-1个里面字典序是否最小,时间复杂度接近o(n*n),所以最好加入若干优化。第一个就是str[j]==str[j+l]弱两个位置字符不同,那就没有最长公共前缀了,可以continue。第二个则是查找到有效的位置j后,那么下次查找的位置则是其最长公共前缀lcp+j这个位置左右。因为是隔l个检查符合,所以下次检查j+lcp/l*l-l及j+l两者靠后的那个。这个不知道为什么wa了所以没写了。。。如果有极端数据10w个a这样的,估计要跑十几秒。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 #define clr(x) memset(x,0,sizeof(x))
  7 #define clr_1(x) memset(x,-1,sizeof(x))
  8 #define LL long long
  9 #define mod 1000000007
 10 #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
 11 #define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)
 12 using namespace std;
 13 const int N=5e5+10;
 14 int wa[N],wb[N],backet[N],order[N],sa[N];
 15 int ranked[N],height[N],s[N],n;
 16 typedef vector<int> vec;
 17 typedef vector<vec> stable;
 18 int st[N][30];
 19 inline int min(int a,int b)
 20 {
 21     return a<b?a:b;
 22 }
 23 inline int max(int a,int b)
 24 {
 25     return a>b?a:b;
 26 }
 27 int c0(int *r,int a,int b)
 28 {
 29     return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
 30 }
 31 int c12(int k,int *r,int a,int b)
 32 {
 33     if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
 34     else return r[a]<r[b]||r[a]==r[b]&&order[a+1]<order[b+1];
 35 }
 36 void sorted(int *r,int *a,int *b,int n,int m)
 37 {
 38     int i;
 39     for(i=0;i<n;i++) order[i]=r[a[i]];
 40     for(i=0;i<m;i++) backet[i]=0;
 41     for(i=0;i<n;i++) backet[order[i]]++;
 42     for(i=1;i<m;i++) backet[i]+=backet[i-1];
 43     for(i=n-1;i>=0;i--) b[--backet[order[i]]]=a[i];
 44     return;
 45 }
 46 void dc3(int *r,int *sa,int n,int m)
 47 {
 48     int i,j,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
 49     int *rn=r+n;
 50     r[n]=r[n+1]=0;
 51     for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
 52     sorted(r+2,wa,wb,tbc,m);
 53     sorted(r+1,wb,wa,tbc,m);
 54     sorted(r,wa,wb,tbc,m);
 55     for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
 56         rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
 57     if(p<tbc) dc3(rn,san,tbc,p);
 58     else for(i=0;i<tbc;i++) san[rn[i]]=i;
 59     for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
 60     if(n%3==1) wb[ta++]=n-1;
 61     sorted(r,wb,wa,ta,m);
 62     for(i=0;i<tbc;i++) order[wb[i]=G(san[i])]=i;
 63     for(i=0,j=0,p=0;i<ta && j<tbc;p++)
 64         sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
 65     for(;i<ta;p++) sa[p]=wa[i++];
 66     for(;j<tbc;p++) sa[p]=wb[j++];
 67     return;
 68 }
 69 void calheight(int *r, int *sa, int n) {
 70     int i, j, k = 0;
 71     for (i = 1; i <= n; i++) ranked[sa[i]] = i;
 72     for (i = 0; i < n; height[ranked[i++]] = k)
 73         for (k ? k-- : 0, j = sa[ranked[i] - 1]; r[i + k] == r[j + k]; k++);
 74     height[1]=0;
 75     return ;
 76 }
 77 void dealst(int n,int *sa)
 78 {
 79     int t=0,k,divk;
 80     for(int i=1;i<n;i++)
 81         st[i][1]=height[i+1];
 82     for(k=4,t=2,divk=2;k<=n;k<<=1,divk<<=1,t++)
 83         for(int i=1;i<=n-k+1;i++)
 84             st[i][t]=min(min(st[i][t-1],st[i+divk][t-1]),height[i+divk]);
 85     return ;
 86 }
 87 int query(int u,int v)
 88 {
 89     u=ranked[u];
 90     v=ranked[v];
 91     if(u>v) swap(u,v);
 92     int p=v-u+1,k=0;
 93     while(p)
 94     {
 95         p>>=1;
 96         k++;
 97     }
 98     return min(st[u][k-1],st[v-(1<<k-1)+1][k-1]);
 99 }
100 int m,ans,maxn,lt,pos,len,now,kase,flag;
101 char str[N];
102 int main()
103 {
104     int T=0;
105     while(++T)
106     {
107          scanf("%s",str);
108          if(str[0]=='#') break;
109          printf("Case %d: ",T);
110          n=strlen(str);
111          for(int i=0;i<n;i++)
112              s[i]=str[i]-'a'+1;
113         s[n++]=0;
114         dc3(s,sa,n,30);
115         n--;
116         calheight(s,sa,n);
117         dealst(n,sa);
118         maxn=1;
119         pos=0;
120         len=n;
121         for(int l=1;l<=n/2;l++)
122         {
123             for(int j=0;j<n-l;j+=l)
124             {
125                 if(str[j]!=str[j+l]) continue;
126                 ans=query(j,j+l);
127                 for(int i=0;i<l;i++)
128                     if(j-i<0 || str[j-i]!=str[j-i+l]) break;
129                     else
130                     {
131                         now=(ans+i)/l+1;
132                         if((now>maxn) || (now==maxn && ranked[j-i]<ranked[pos]))
133                         {
134                             maxn=now;
135                             pos=j-i;
136                             len=l;
137                         }
138                     }
139             }
140         }
141         if(maxn==1) printf("%c
",str[sa[1]]);
142         else
143         {
144             m=pos+len*maxn;
145             for(int i=pos;i<m;i++)
146                 printf("%c",str[i]);
147             printf("
");
148         }
149     }
150     return 0;
151 }
View Code
POJ 2774
Long Long Message
Time Limit: 4000MS   Memory Limit: 131072K
Total Submissions: 31753   Accepted: 12810
Case Time Limit: 1000MS

Description

The little cat is majoring in physics in the capital of Byterland. A piece of sad news comes to him these days: his mother is getting ill. Being worried about spending so much on railway tickets (Byterland is such a big country, and he has to spend 16 shours on train to his hometown), he decided only to send SMS with his mother. 

The little cat lives in an unrich family, so he frequently comes to the mobile service center, to check how much money he has spent on SMS. Yesterday, the computer of service center was broken, and printed two very long messages. The brilliant little cat soon found out: 

1. All characters in messages are lowercase Latin letters, without punctuations and spaces. 
2. All SMS has been appended to each other – (i+1)-th SMS comes directly after the i-th one – that is why those two messages are quite long. 
3. His own SMS has been appended together, but possibly a great many redundancy characters appear leftwards and rightwards due to the broken computer. 
E.g: if his SMS is “motheriloveyou”, either long message printed by that machine, would possibly be one of “hahamotheriloveyou”, “motheriloveyoureally”, “motheriloveyouornot”, “bbbmotheriloveyouaaa”, etc. 
4. For these broken issues, the little cat has printed his original text twice (so there appears two very long messages). Even though the original text remains the same in two printed messages, the redundancy characters on both sides would be possibly different. 

You are given those two very long messages, and you have to output the length of the longest possible original text written by the little cat. 

Background: 
The SMS in Byterland mobile service are charging in dollars-per-byte. That is why the little cat is worrying about how long could the longest original text be. 

Why ask you to write a program? There are four resions: 
1. The little cat is so busy these days with physics lessons; 
2. The little cat wants to keep what he said to his mother seceret; 
3. POJ is such a great Online Judge; 
4. The little cat wants to earn some money from POJ, and try to persuade his mother to see the doctor :( 

Input

Two strings with lowercase letters on two of the input lines individually. Number of characters in each one will never exceed 100000.

Output

A single line with a single integer number – what is the maximum length of the original text written by the little cat.

Sample Input

yeshowmuchiloveyoumydearmotherreallyicannotbelieveit
yeaphowmuchiloveyoumydearmother

Sample Output

27


emmm,水题把,把两串之间夹一个从未出现的最小数字,然后连起来,求其height。答案就是sa[i-1],sa[i]分属不同两串的最大的height。
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 #define clr(x) memset(x,0,sizeof(x))
  7 #define clr_1(x) memset(x,-1,sizeof(x))
  8 #define LL long long
  9 #define mod 1000000007
 10 #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
 11 #define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)
 12 using namespace std;
 13 const int N=6e5+10;
 14 const int M=1e5+10;
 15 int wa[N],wb[N],backet[N],order[N],sa[N];
 16 int ranked[2*M],height[2*M],s[N],n;
 17 inline int min(int a,int b)
 18 {
 19     return a<b?a:b;
 20 }
 21 inline int max(int a,int b)
 22 {
 23     return a>b?a:b;
 24 }
 25 int c0(int *r,int a,int b)
 26 {
 27     return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
 28 }
 29 int c12(int k,int *r,int a,int b)
 30 {
 31     if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
 32     else return r[a]<r[b]||r[a]==r[b]&&order[a+1]<order[b+1];
 33 }
 34 void sorted(int *r,int *a,int *b,int n,int m)
 35 {
 36     int i;
 37     for(i=0;i<n;i++) order[i]=r[a[i]];
 38     for(i=0;i<m;i++) backet[i]=0;
 39     for(i=0;i<n;i++) backet[order[i]]++;
 40     for(i=1;i<m;i++) backet[i]+=backet[i-1];
 41     for(i=n-1;i>=0;i--) b[--backet[order[i]]]=a[i];
 42     return;
 43 }
 44 void dc3(int *r,int *sa,int n,int m)
 45 {
 46     int i,j,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
 47     int *rn=r+n;
 48     r[n]=r[n+1]=0;
 49     for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
 50     sorted(r+2,wa,wb,tbc,m);
 51     sorted(r+1,wb,wa,tbc,m);
 52     sorted(r,wa,wb,tbc,m);
 53     for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
 54         rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
 55     if(p<tbc) dc3(rn,san,tbc,p);
 56     else for(i=0;i<tbc;i++) san[rn[i]]=i;
 57     for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
 58     if(n%3==1) wb[ta++]=n-1;
 59     sorted(r,wb,wa,ta,m);
 60     for(i=0;i<tbc;i++) order[wb[i]=G(san[i])]=i;
 61     for(i=0,j=0,p=0;i<ta && j<tbc;p++)
 62         sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
 63     for(;i<ta;p++) sa[p]=wa[i++];
 64     for(;j<tbc;p++) sa[p]=wb[j++];
 65     return;
 66 }
 67 void calheight(int *r, int *sa, int n) {
 68     int i, j, k = 0;
 69     for (i = 1; i <= n; i++) ranked[sa[i]] = i;
 70     for (i = 0; i < n; height[ranked[i++]] = k)
 71         for (k ? k-- : 0, j = sa[ranked[i] - 1]; r[i + k] == r[j + k]; k++);
 72     return ;
 73 }
 74 int m,ans,maxn,lt,pos,len,now,kase,flag;
 75 char str1[M],str2[M];
 76 int main()
 77 {
 78     while(scanf("%s%s",str1,str2)!=EOF)
 79     {
 80         n=strlen(str1);
 81         for(int i=0;i<n;i++)
 82             s[i]=str1[i]-'a'+2;
 83         s[n++]=1;
 84         m=strlen(str2);
 85         for(int i=n;i<n+m;i++)
 86             s[i]=str2[i-n]-'a'+2;
 87         n+=m;
 88         m=strlen(str1);
 89         s[n++]=0;
 90         dc3(s,sa,n,30);
 91         n--;
 92         maxn=0;
 93         calheight(s,sa,n);
 94         for(int i=2;i<=n;i++)
 95             if(height[i]>maxn)
 96             {
 97                 if(sa[i-1]<m && sa[i]>m)
 98                     maxn=height[i];
 99                 if(sa[i-1]>m && sa[i]<m)
100                     maxn=height[i];
101             }
102         printf("%d
",maxn);
103     }
104     return 0;
105 }
View Code

poj 3415

Common Substrings
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 11380   Accepted: 3761

Description

A substring of a string T is defined as:

T(ik)=TiTi+1...Ti+k-1, 1≤ii+k-1≤|T|.

Given two strings AB and one integer K, we define S, a set of triples (ijk):

S = {(ijk) | kKA(ik)=B(jk)}.

You are to give the value of |S| for specific AB and K.

Input

The input file contains several blocks of data. For each block, the first line contains one integer K, followed by two lines containing strings A and B, respectively. The input file is ended by K=0.

1 ≤ |A|, |B| ≤ 105
1 ≤ K ≤ min{|A|, |B|}
Characters of A and B are all Latin letters.

Output

For each case, output an integer |S|.

Sample Input

2
aababaa
abaabaa
1
xx
xx
0

Sample Output

22
5

求两串中重复子串(位置不一样的相同子串是不同的)的长度大于k的重复子串个数。

把两串中间隔一个最小的数字接在一起后,那么这题就变成了height分组问题了--height按照最小为k区分组。按照sa的顺序到i以后,我们算出该分组前面的每个sa所对应的后缀和该点的后缀的最长公共前缀长度h,那么对答案贡献就是(h-k+1)。

可以用前缀和和单调栈快速近似O(1)求出。

具体做法是做个单调递增栈,即求最小值的单调递增栈。每个栈元素k(k代表他是栈底向上第k个元素)包括他的height值和height值的位置pos-1(sa位置),即他的位置值kpos=pos-1。每到达一个新位置(sa位置,后同)i,他都对应一个单调栈。栈里每个元素对代表什么呢?它代表某个位置到当前位置i的height最小值,即某个字符串位置的后缀和当前位置的后缀的最长公共前缀,这样的位置是对应在sa上是一段的,不妨称为最小值段。假如这个元素是栈底向上第k个元素,那他代表的最小值段是第k-1个元素的(k-1)pos+1,到当前元素k的kpos,这一段里面的后缀和当前位置i的最长公共前缀为height[k]。

这样就先是把时间复杂度减少了一部分。但不可能每次都遍历一遍栈。我们多增加一个数组ans,保存从分组最前位置到当前栈内元素位置kpos的串总数(这样的一个段由几个最小值段组成)。因为栈内元素的ans一旦确定即使i改变也是不会改变的(想想为什么),因此每次确定了i的单调栈,就能从top前一个元素的ans递推出top的ans。这样访问每个点都是O(1)的。把top的ans加入答案即可。当然由于是两个串,你得分a串和b串。每次都得递推a串和b串在该位置上的ansa,ansb。而求每个位置属于a串的前缀和属于b串的前缀,是为了快速求出两个相邻位置栈内元素之间a串和b串后缀的数量。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 #define clr(x) memset(x,0,sizeof(x))
  7 #define clr_1(x) memset(x,-1,sizeof(x))
  8 #define LL long long
  9 #define mod 1000000007
 10 #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
 11 #define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)
 12 using namespace std;
 13 const int N=1e6+10;
 14 const int M=2e5+10;
 15 int wa[N],wb[N],backet[N],order[N],sa[N];
 16 int ranked[2*M],height[2*M],s[N],n,stack[2*M],pos[2*M],top,suma[2*M],sumb[2*M];
 17 LL ansa[2*M],ansb[2*M];
 18 inline int min(int a,int b)
 19 {
 20     return a<b?a:b;
 21 }
 22 inline int max(int a,int b)
 23 {
 24     return a>b?a:b;
 25 }
 26 int c0(int *r,int a,int b)
 27 {
 28     return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
 29 }
 30 int c12(int k,int *r,int a,int b)
 31 {
 32     if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
 33     else return r[a]<r[b]||r[a]==r[b]&&order[a+1]<order[b+1];
 34 }
 35 void sorted(int *r,int *a,int *b,int n,int m)
 36 {
 37     int i;
 38     for(i=0;i<n;i++) order[i]=r[a[i]];
 39     for(i=0;i<m;i++) backet[i]=0;
 40     for(i=0;i<n;i++) backet[order[i]]++;
 41     for(i=1;i<m;i++) backet[i]+=backet[i-1];
 42     for(i=n-1;i>=0;i--) b[--backet[order[i]]]=a[i];
 43     return;
 44 }
 45 void dc3(int *r,int *sa,int n,int m)
 46 {
 47     int i,j,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
 48     int *rn=r+n;
 49     r[n]=r[n+1]=0;
 50     for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
 51     sorted(r+2,wa,wb,tbc,m);
 52     sorted(r+1,wb,wa,tbc,m);
 53     sorted(r,wa,wb,tbc,m);
 54     for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
 55         rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
 56     if(p<tbc) dc3(rn,san,tbc,p);
 57     else for(i=0;i<tbc;i++) san[rn[i]]=i;
 58     for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
 59     if(n%3==1) wb[ta++]=n-1;
 60     sorted(r,wb,wa,ta,m);
 61     for(i=0;i<tbc;i++) order[wb[i]=G(san[i])]=i;
 62     for(i=0,j=0,p=0;i<ta && j<tbc;p++)
 63         sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
 64     for(;i<ta;p++) sa[p]=wa[i++];
 65     for(;j<tbc;p++) sa[p]=wb[j++];
 66     return;
 67 }
 68 void calheight(int *r, int *sa, int n) {
 69     int i, j, k = 0;
 70     for (i = 1; i <= n; i++) ranked[sa[i]] = i;
 71     for (i = 0; i < n; height[ranked[i++]] = k)
 72         for (k ? k-- : 0, j = sa[ranked[i] - 1]; r[i + k] == r[j + k]; k++);
 73     return ;
 74 }
 75 int m,maxn,k,cta,ctb,minn;
 76 LL ans;
 77 char str1[M],str2[M];
 78 int main()
 79 {
 80     while(scanf("%d",&k)!=EOF && k!=0)
 81     {
 82         scanf("%s%s",str1,str2);
 83         n=strlen(str1);
 84         for(int i=0;i<n;i++)
 85             s[i]=str1[i]+2;
 86         s[n++]=1;
 87         m=strlen(str2);
 88         for(int i=n;i<n+m;i++)
 89             s[i]=str2[i-n]+2;
 90         n+=m;
 91         m=strlen(str1);
 92         s[n++]=0;
 93         dc3(s,sa,n,200);
 94         n--;
 95         calheight(s,sa,n);
 96         suma[0]=sumb[0]=suma[1]=sumb[1]=0;
 97         for(int i=2;i<=n;i++)
 98         if(sa[i]>m)
 99         {
100             sumb[i]=sumb[i-1]+1;
101             suma[i]=suma[i-1];
102         }
103         else
104         {
105             sumb[i]=sumb[i-1];
106             suma[i]=suma[i-1]+1;        
107         }
108         ans=0;
109         top=0;
110         pos[0]=1;
111         ansa[0]=0;
112         ansb[0]=0;
113         for(int i=3;i<=n;i++)
114         {
115             if(height[i]<k)
116             {
117                 top=0;
118                 pos[0]=i-1;
119             }
120             else
121             {
122                 while(top>0 && stack[top]>=height[i]) top--;
123                 stack[++top]=height[i];
124                 pos[top]=i-1;
125                 ansa[top]=ansa[top-1]+(LL)(suma[pos[top]]-suma[pos[top-1]])*(LL)(stack[top]-k+1);
126                 ansb[top]=ansb[top-1]+(LL)(sumb[pos[top]]-sumb[pos[top-1]])*(LL)(stack[top]-k+1);    
127                 if(sa[i]>m)
128                     ans+=ansa[top];
129                 else if(sa[i]<m)
130                     ans+=ansb[top];
131             }
132         }
133         printf("%lld
",ans);
134     }
135     return 0;
136 }
View Code


原文地址:https://www.cnblogs.com/wujiechao/p/7512287.html