HDU 4763 Theme Section

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4763

-------------------------------------------------------------------------------------------

数据范围卡了$SA$但数据却没能构造到卡一些理论复杂度更高的方法

这里说一下比较靠谱的$exkmp$的做法

根据$exkmp$的$next$数组定义

我们可以用$O(n)$的时间得到一个后缀与整个串的最长公共前缀的长度

然后我们就可以根据$next[n - i + 1]$与$i$是否相等判断前后缀是否相等

 

而对于中间的部分 我们知道如果 $next[i + 1]$到$next[n - i]$中的最大值不小于$i$

那么$i$即为一个可行解

但此处直接扫描的话复杂度显然不够 再观察可以发现如果我们把答案从大到小枚举

那么这个取最大值区间的范围是逐渐增大的 于是均摊下来的复杂度还是线性的

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6 const int N = 1e6 + 10;
 7 char s[N];
 8 int nexte[N];
 9 int t, ans, n;
10 int main()
11 {
12     scanf("%d", &t);
13     while(t--)
14     {
15         scanf("%s", s + 1);
16         n = strlen(s + 1);
17         if(n <= 2)
18         {
19             puts("0");
20             continue;
21         }
22         nexte[1] = n;
23         int id = 2, p = 1;
24         while(p < n && s[p] == s[p + 1])
25             ++p;
26         nexte[2] = p - 1;
27         for(int i = 3; i <= n; ++i)
28         {
29             int l = nexte[i - id + 1];
30             if(i + l <= p)
31                 nexte[i] = l;
32             else
33             {
34                 p = max(p, i - 1);
35                 while(p < n && s[p - i + 2] == s[p + 1])
36                     ++p;
37                 nexte[i] = p - i + 1;
38                 id = i;
39             }
40         }
41         int len = n / 3, mx = 0;
42         for(int i = len + 1; i <= n - len; ++i)
43             mx = max(mx, nexte[i]);
44         ans = 0;
45         for(int i = len; i; --i)
46         {
47             if(nexte[n - i + 1] == i && mx >= i)
48             {
49                 ans = i;
50                 break;
51             }
52             mx = max(mx, nexte[i]);
53             mx = max(mx, nexte[n - i + 1]);
54         }
55         printf("%d\n", ans);
56     }
57     return 0;
58 }

 

posted @ 2016-02-20 15:16  sagitta  阅读(277)  评论(0编辑  收藏  举报