hdu4763 Theme Section【next数组应用】

时间:2023-01-03 17:44:00

Theme Section

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


Problem Description
It's time for music! A lot of popular musicians are invited to join us in the music festival. Each of them will play one of their representative songs. To make the programs more interesting and challenging, the hosts are going to add some constraints to the rhythm of the songs, i.e., each song is required to have a 'theme section'. The theme section shall be played at the beginning, the middle, and the end of each song. More specifically, given a theme section E, the song will be in the format of 'EAEBE', where section A and section B could have arbitrary number of notes. Note that there are 26 types of notes, denoted by lower case letters 'a' - 'z'.

To get well prepared for the festival, the hosts want to know the maximum possible length of the theme section of each song. Can you help us?
 

 

Input
The integer N in the first line denotes the total number of songs in the festival. Each of the following N lines consists of one string, indicating the notes of the i-th (1 <= i <= N) song. The length of the string will not exceed 10^6.
 

 

Output
There will be N lines in the output, where the i-th line denotes the maximum possible length of the theme section of the i-th song.
 

 

Sample Input
5 xy abc aaa aaaaba aaxoaaaaa
 

 

Sample Output
0 0 1 1 2
 

 

Source
 

 

Recommend
liuyiding

 

题意:

有$n$个字符串,找到每个字符串中最长的一段子串。要求这段子串在字符串的开头,中间和结尾都出现过。输出子串长度。

思路:

果然题目做多了一看就能有思路。

要在开头和结尾都出现过,显然这个串的长度不可能大于$next[len]$。

因为$next[len]$表示的就是$S[1,len]$中,前缀和后缀匹配的最长的长度。

然后我们就要去找中间的。

现在我们已经知道$S[1,nxt[len]$和$S[len - nxt[len]+1,len]$是匹配的了,答案只能比他们更小

对于$S[nxt[len],len-nxt[len]+1]$的部分,我们去找每一个位置对应的$next$。

最大的那一个$next$就表示,可以找到的最长的一段既在开头出现又在中间出现的子串。

这个最大值和$nxt[len]$的较小值就是答案。

$len-nxt[len]+1$之后的部分为什么不找呢,因为如果找到了也是重叠了,画个图会发现这样是不可行的。

 1 #include<iostream>
 2 #include<bits/stdc++.h>
 3 #include<cstdio>
 4 #include<cmath>
 5 //#include<cstdlib>
 6 #include<cstring>
 7 #include<algorithm>
 8 //#include<queue>
 9 #include<vector>
10 //#include<set>
11 //#include<climits>
12 //#include<map>
13 using namespace std;
14 typedef long long LL;
15 typedef unsigned long long ull;
16 #define N 100010
17 #define pi 3.1415926535
18 #define inf 0x3f3f3f3f
19 
20 const int maxn = 1e6 + 5;
21 int n;
22 char str[maxn];
23 int nxt[maxn];
24 
25 void get_nxt(char *s)
26 {
27     int len = strlen(s + 1);
28     nxt[1] = 0;
29     for(int i = 2, j = 0; i <= len; i++){
30         while(j > 0 && s[i] != s[j + 1])j = nxt[j];
31         if(s[i] == s[j + 1])j++;
32         nxt[i] = j;
33     }
34 }
35 
36 int main()
37 {
38     while(scanf("%d", &n) != EOF){
39         for(int i = 0; i < n; i++){
40             scanf("%s", str + 1);
41             get_nxt(str);
42             int len = strlen(str + 1);
43             int mx = -1;
44             //cout<<nxt[len]<<endl;
45             for(int i = nxt[len]; i <= len - nxt[len] + 1; i++){
46                 //cout<<nxt[i]<<endl;
47                 mx = max(mx, nxt[i]);
48             }
49             printf("%d\n", min(mx, nxt[len]));
50         }
51     }
52     return 0;
53 }