String Problem HDU - 3374

原题链接

考察: KMP+字符串的最小最大表示法

如果不懂字符串的最小最大表示法走这:GO (我认为是讲得很详细的)

当我们利用字符串的最小最大表示法求最小值和最大值下标后,直接利用next数组求循环节即可(如果最小/大值在循环字符串里出现多次,那么此字符串就可以构成循环节,并且循环节长度小于字符串长度一半)

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int N = 2000010;
 6 char s[N],tmp[N];
 7 int len,ne[N];
 8 int get(int id)
 9 { 
10     int i = 1,j=2,k;
11     while(i<=len&&j<=len)
12     {
13         for(k=0;k<len&&tmp[i+k]==tmp[j+k];k++);
14         if(k==len) break;
15         if(tmp[i+k]>tmp[j+k])
16         {
17             if(id)
18             {
19                 i = i+k+1;
20                 if(i==j) i++;
21             }else{
22                 j = j+k+1;
23                 if(i==j) j++;
24             }
25         }else if(tmp[i+k]<tmp[j+k])
26         {
27             if(id)
28             {
29                 j = j+k+1;
30                 if(i==j) j++;
31             }else{
32                 i = i+k+1;
33                 if(i==j) i++;
34             }
35         }
36     }
37     int ans = min(i,j);
38     return ans;
39 }
40 int main()
41 {
42     while(scanf("%s",s+1)!=EOF)
43     {
44         len = strlen(s+1);
45         for(int i=1;i<=len;i++) tmp[len+i] = s[i],tmp[i] = s[i];
46         tmp[len*2+1] = '\0'; 
47         int l = get(1),r = get(0);
48         memset(ne,0,sizeof ne);
49         for(int i=2,j=0;i<=len;i++)
50         {
51             while(j&&s[j+1]!=s[i]) j = ne[j];
52             if(s[j+1]==s[i]) j++;
53             ne[i] = j;
54         }
55         int lens = len-ne[len],cnt = 0;
56         if(len%lens==0) cnt = len/lens;
57         else cnt = 1;
58         printf("%d %d %d %d\n",l,cnt,r,cnt);
59     }
60     return 0;
61 }

 

posted @ 2021-01-01 09:21  acmloser  阅读(76)  评论(0编辑  收藏  举报