SGU 439 A Secret Book

解法:

  对于第二个串,循环移动能得到的字典序最小的串,可以直接用最小表示法搞定。

  然后用最小表示的第二个串和第一个串做两次扩展KMP,一次正常求,另外一次将两个串都反转一下,然后扫一遍ex[]数组

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N = (int)2e6+10;
 6 char a[N],b[N],c[N];
 7 int next[N],exa[N],exb[N];
 8 void getnext(char *s){
 9     int len = strlen(s),cur = 0;
10     next[0] = len;
11     while(cur < len&&s[cur]==s[cur+1])cur++;
12     next[1] = cur;cur = 1;
13     for(int k = 2;k<len;k++){
14         int p = cur + next[cur] - 1,L = next[k-cur];
15         if(k + L -1 >= p){
16             int j = (p-k+1)>0?(p-k+1):0;
17             while(k+j<len&&s[k+j]==s[j])j++;
18             next[k] = j;
19             cur = k;
20         }else
21             next[k] = L;
22     }
23 }
24 void exkmp(char *s1,char *s2,int *ex){
25     getnext(s2);
26     int l1 = strlen(s1),l2 = strlen(s2),cur = 0;
27     while(cur < min(l1,l2)&&s1[cur]==s2[cur])cur++;
28     ex[0] = cur;cur = 0;
29     for(int k = 1;k < l1;k++){
30         int p = cur + ex[cur] - 1,L = next[k-cur];
31         if(k + L -1 >= p){
32             int j = (p-k+1)>0?(p-k+1):0;
33             while(k+j<l1&&j<l2&&s1[k+j]==s2[j])j++;
34             ex[k] = j;
35             cur = k;
36         }else
37             ex[k] = L;
38     }
39 }
40 int MinRep(char *s){
41     int i = 0,j = 1,k = 0,t,len = strlen(s);
42     while(i<len&&j<len&&k<len){
43         t = s[(i+k)%len] - s[(j+k)%len];
44         if(t==0)k++;
45         else{
46             if(t>0)
47                 i += k + 1;
48             else
49                 j += k + 1;
50             if(i==j)j++;
51             k = 0;
52         }
53     }
54     return min(i,j);
55 }
56 inline int dis(int now,int sz){
57     return min(now,sz-now-1);
58 }
59 int main(){
60     int n,m;
61     while(~scanf("%d%d",&n,&m)){
62         scanf("%s%s",a,b);
63         int start = MinRep(b);
64         for(int i = 0,j = start;i < m;i++,j = (j+1)%m)c[i] = b[j];c[m] = 0;
65         for(int i = n;i < n+n;i++)a[i] = a[i-n];a[n+n] = 0;
66         exkmp(a,c,exa);
67         reverse(a,a+2*n);reverse(c,c+m);
68         exkmp(a,c,exb);
69         reverse(exb,exb+n*2);
70         reverse(c,c+m);
71         reverse(a,a+2*n);
72         int ans = -1;
73         for(int i = 0;i < n;i++)
74             if(exa[i] == m || exa[i] + exb[i+m-1] == m-1){
75                 if(ans==-1)ans = i;
76                 else if(dis(i,n)<dis(ans,n))ans = i;
77             }
78         puts(c);
79         for(int i = 0,j = ans;i < n;i++,j = (j+1)%n)putchar(a[j]);puts("");
80     }
81     return 0;
82 }
原文地址:https://www.cnblogs.com/silver-bullet/p/3141071.html