HDU 4763 (KMP)

PS参考:http://m.blog.csdn.net/blog/biboyouyun/12206733

题意:EAEBE这种结构的字符串,求E的最大长度;

分析:我直接就从s.length()/3开始枚举,结果TLE了,正解是KMP,但是string的substr和find能够水过,只能说学弟太强了(TLE了一次就想怎么减时间,而且还是想怎么通过后台数据找时间,而不是找正解)。

PS:目前还没彻底搞懂KMP算法,只是能用模板的程度,next[]数组表示前缀和后缀的最长长度,next [ i ]决定了1 ~ next [ i ]这个子串一定在str中作为后缀出现,那么我们就是要找一个i(从next[n]推来,不行就i = next [ i ] ),要使1 ~ i 在i + 1 ~ str.length() - i 也有这个子串,那么如何保证子串之间不重叠?就是 3 * i <=length 然后枚举2*i到length - i的每一个next[j]看有没有next [ j ] == i 就可以了

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <sstream>
 4 #include <cmath>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <string>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <queue>
12 #include <stack>
13 #include <algorithm>
14 using namespace std;
15 #define ll long long
16 #define _cle(m, a) memset(m, a, sizeof(m))
17 #define repu(i, a, b) for(int i = a; i < b; i++)
18 #define repd(i, a, b) for(int i = b; i >= a; i--)
19 #define sfi(n) scanf("%d", &n)
20 #define sfl(n) scanf("%I64d", &n)
21 #define pfi(n) printf("%d\n", n)
22 #define pfl(n) printf("%I64d\n", n)
23 #define MAXN 1000005
24 char s[MAXN];
25 int Next[MAXN];
26 bool flag[MAXN];
27 int main()
28 {
29     int T;
30     scanf("%d",&T);
31     while(T--)
32     {
33         scanf("%s", s);
34         int l = strlen(s);
35         int i = 0, j = -1;
36         Next[0] = -1;
37         while(i < l)
38         {
39             while(j != -1 && s[i]!=s[j]) j = Next[j];
40             Next[++i]=++j;
41         }
42         memset(flag, 0, sizeof(flag));
43         int t = l;
44         while(t > 0)
45         {
46             if(l >= 2*t)
47                 flag[t] = true;
48             t = Next[t];
49         }
50         int ans = 0;
51         for(int i = l-1; i > 1; i--)
52         {
53             t = i;
54             while(t > 0)
55             {
56                 if(flag[t] && l >= i+t && i >= 2*t)
57                 {
58                     ans = max(ans,t);
59                     break;
60                 }
61                 t = Next[t];
62             }
63         }
64         printf("%d\n",ans);
65     }
66     return 0;
67 }
正解KMP
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <sstream>
 4 #include <cmath>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <string>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <queue>
12 #include <stack>
13 #include <algorithm>
14 using namespace std;
15 #define ll long long
16 #define _cle(m, a) memset(m, a, sizeof(m))
17 #define repu(i, a, b) for(int i = a; i < b; i++)
18 #define repd(i, a, b) for(int i = b; i >= a; i--)
19 #define sfi(n) scanf("%d", &n)
20 #define sfl(n) scanf("%I64d", &n)
21 #define pfi(n) printf("%d\n", n)
22 #define pfl(n) printf("%I64d\n", n)
23 #define MAXN 1000005
24 int main()
25 {
26     ios::sync_with_stdio(false);
27     string s;
28     int T;
29     cin>>T;
30     while(T--)
31     {
32         cin>>s;
33         int l = s.length();
34         int h = l/3,t = 0;
35         for(int i=h; i>=1; i--)
36         {
37             if(s[i-1] != s[l-1])///数据太水了,加上这个优化就可以过,否则TLE
38             {
39                 continue;
40             }
41             string s1 = s.substr(0,i);
42             int j = l - i;
43             string s2 = s.substr(j,i);
44             if(s1 == s2)
45             {
46                 s2 = s.substr(i,l-2*i);
47                 if(s2.find(s1) != s2.npos)
48                 {
49                     t = i;
50                     break;
51                 }
52             }
53         }
54         cout<<t<<endl;
55     }
56     return 0;
57 }
string水过

 如果想理解的更深一步的话,推荐题目HDU3746

posted @ 2015-08-10 18:33  一麻袋码的玛侬  阅读(210)  评论(0编辑  收藏  举报