• 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 }
  • 相关阅读:
    java 接口的定义即实现
    进程的pv。。
    变量,常量,字符,字符串,数组的声明及初始化
    运算符重载
    数组大小的声明 1到100的素数
    第十二周助教总结(2021.4.192021.4.25)
    第十周助教总结(2021.4.52021.4.11)
    第十一周助教总结(2021.4.122021.4.18)
    助教周报(第一轮)王冰炜
    ThinkPHP3.1.2整合UCenter详解(一)
  • 原文地址:https://www.cnblogs.com/silver-bullet/p/3141071.html
Copyright © 2020-2023  润新知