• bzoj2740 串 && bzoj2176 strange string(最小表示法模板)


    https://konnyakuxzy.github.io/BZPRO/JudgeOnline/2740.html

    题解讲的很清楚了

    (好像等于的情况应该归入case2而不是case1?并不确定)

    具体方法:

    将串翻转,找到字典序最小且最短的后缀,然后找到以这个后缀为纯循环节的最长后缀T,则第一步是将这个后缀T提到最前面;

    然后第二步是把整个串除T外部分变为其循环同构串的最小表示。

    要找到字典序最小且最短的后缀,只要找到整个串的最小表示法(设最小表示法在位置i开始),然后找到S[i..n]的最短公共前后缀即可(容易发现是对的)(见代码1);也可以直接用最小表示法类似的方法一次直接求出来(见代码2)

    代码1:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 using namespace std;
     6 #define fi first
     7 #define se second
     8 #define mp make_pair
     9 #define pb push_back
    10 typedef long long ll;
    11 typedef unsigned long long ull;
    12 typedef pair<int,int> pii;
    13 
    14 int T;
    15 char s[10000100];
    16 int f[10000100];
    17 int calc(const char *s,int n)
    18 {
    19     int i=0,j=1,k=0,t;
    20     while(i<n&&j<n&&k<n)
    21     {
    22         t=s[(i+k)%n]-s[(j+k)%n];
    23         if(t==0)    ++k;
    24         else
    25         {
    26             if(t>0)    i+=k+1;
    27             else    j+=k+1;
    28             if(i==j)    ++j;
    29             k=0;
    30         }
    31     }
    32     return min(i,j);
    33 }
    34 int n;
    35 int an1,an2;
    36 int main()
    37 {
    38     int i,j,t;
    39     scanf("%d",&T);
    40     while(T--)
    41     {
    42         scanf("%s",s);n=strlen(s);
    43         reverse(s,s+n);
    44         t=calc(s,n);
    45         //printf("1t%d
    ",t);
    46         //t=0;
    47         f[t]=0;
    48         for(i=t+1,j=0;i<n;++i)
    49         {
    50             //j=f[i-1];
    51             while(j>0&&s[t+j]!=s[i])    j=f[t+j-1];
    52             //printf("2t%d %c %c
    ",j,s[t+j],s[i]);
    53             if(s[t+j]==s[i])    ++j;
    54             //printf("1t%d %d %d
    ",i,t+j,s[t+j]==s[i]);
    55             f[i]=j;
    56         }
    57         //for(i=t;i<n;++i)    printf("%d %d
    ",i,f[i]);
    58         j=f[n-1];
    59         if(j)
    60         {
    61             while(f[t+j-1]>0)    j=f[t+j-1];
    62             t=n-j;
    63         }
    64         //printf("1t%d
    ",t);
    65         for(j=t;;)
    66         {
    67             //printf("3t%d %d
    ",j-(n-t),t);
    68             if(j>=n-t&&strncmp(s+(j-(n-t)),s+t,n-t)==0)
    69                 j-=n-t;
    70             else
    71                 break;
    72         }
    73         t=j;
    74         //printf("2t%d
    ",t);
    75         an1=n-t;
    76         //printf("%d
    ",an1);
    77         //printf("%d
    ",t);
    78         t=calc(s,t);
    79         an2=n-t;
    80         printf("%d %d
    ",an1,an2);
    81     }
    82     return 0;
    83 }
    View Code

    代码2:(话说这个复杂度真的对吗?不确定啊?不过实测全a串还有一些随机的串的确是O(n)的,并且能A掉题)

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 using namespace std;
     6 #define fi first
     7 #define se second
     8 #define mp make_pair
     9 #define pb push_back
    10 typedef long long ll;
    11 typedef unsigned long long ull;
    12 typedef pair<int,int> pii;
    13 int T;
    14 char s[10000100];
    15 //int f[10000100];
    16 int calc(const char *s,int n)
    17 {
    18     int i=0,j=1,k=0,t;
    19     while(i<n&&j<n&&k<n)
    20     {
    21         t=s[(i+k)%n]-s[(j+k)%n];
    22         if(t==0)    ++k;
    23         else
    24         {
    25             if(t>0)    i+=k+1;
    26             else    j+=k+1;
    27             if(i==j)    ++j;
    28             k=0;
    29         }
    30     }
    31     return min(i,j);
    32 }
    33 int n;
    34 int an1,an2;
    35 int main()
    36 {
    37     int i,j,k,t;
    38     scanf("%d",&T);
    39     while(T--)
    40     {
    41         scanf("%s",s);
    42         n=strlen(s);
    43         reverse(s,s+n);
    44         i=0;j=1;k=0;
    45         //int tt=0;
    46         while(i<n&&j<n&&k<n)
    47         {
    48             //++tt;
    49             //printf("1t%d %d %d
    ",i,j,k);
    50             t=((i+k<n)?s[i+k]:0)-((j+k<n)?s[j+k]:0);
    51             if(t==0)    ++k;
    52             else
    53             {
    54                 if(t>0)    i+=(j+k<n)?k+1:k;
    55                 else    j+=(i+k<n)?k+1:k;
    56                 if(i==j)    ++j;
    57                 k=0;
    58             }
    59         }
    60         //printf("1t%d
    ",tt);
    61         t=min(i,j);
    62         for(j=t;;)
    63         {
    64             if(j>=n-t&&strncmp(s+(j-(n-t)),s+t,n-t)==0)
    65                 j-=n-t;
    66             else
    67                 break;
    68         }
    69         t=j;
    70         an1=n-t;
    71         t=calc(s,t);
    72         an2=n-t;
    73         printf("%d %d
    ",an1,an2);
    74     }
    75     return 0;
    76 }
    View Code

    https://konnyakuxzy.github.io/BZPRO/JudgeOnline/2176.html

    最小表示法板子

    题解

    这题数据范围比较诡异,一定要用unsigned char。。。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 using namespace std;
     6 #define fi first
     7 #define se second
     8 #define mp make_pair
     9 #define pb push_back
    10 typedef long long ll;
    11 typedef unsigned long long ull;
    12 typedef pair<int,int> pii;
    13 unsigned char s[10000100];
    14 int calc(const unsigned char *s,int n)
    15 {
    16     int i=0,j=1,k=0,t;
    17     while(i<n&&j<n&&k<n)
    18     {
    19         t=s[(i+k)%n]-s[(j+k)%n];
    20         if(t==0)    ++k;
    21         else
    22         {
    23             if(t>0)    i+=k+1;
    24             else    j+=k+1;
    25             if(i==j)    ++j;
    26             k=0;
    27         }
    28     }
    29     return min(i,j);
    30 }
    31 int n;
    32 int main()
    33 {
    34     int t;
    35     scanf("%d%s",&n,s);
    36     t=calc(s,n);
    37     printf("%s",s+t);
    38     s[t]=0;
    39     printf("%s",s);
    40     return 0;
    41 }
    View Code
  • 相关阅读:
    线程池学习笔记
    线性表的顺序存储和链式存储的实现(C)
    二叉树遍历算法——包含递归前、中、后序和层次,非递归前、中、后序和层次遍历共八种
    【Linux学习笔记】栈与函数调用惯例
    Linux网络编程简单示例
    Linux常用C函数-接口处理篇(网络通信函数)
    android的快速开发框架集合
    Android访问网络数据的几种方式Demo
    Linux C函数库大全
    Mysql 之配置文件my.cnf
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9839726.html
Copyright © 2020-2023  润新知