• 初涉最小表示法&&bzoj1398: Vijos1382寻找主人 Necklace


    把最小表示法的坑填了

    Description

    给定两个项链的表示,判断他们是否可能是一条项链。

    Input

    输入文件只有两行,每行一个由0至9组成的字符串,描述一个项链的表示(保证项链的长度是相等的)。

    Output

    如果两条项链不可能同构,那么输出’No’,否则的话,第一行输出一个’Yes’
    第二行输出该项链的字典序最小的表示。 设L = 项链长度,L <= 1000000。

    Sample Input

    2234342423
    2423223434

    Sample Output

    Yes
    2234342423

    题目分析

    这里有最小表示法的论文https://wenku.baidu.com/view/c6c5e7335a8102d276a22fa6.html。

    关键在于if (s[(i+k)%n]!=s[(j+k)%n])时的快速重配。

    还有值得注意的是重配之后i有可能等于j,所以要i++,这个细节处理挺容易忘掉的。

    是种挺优美的思想。

     1 #include<bits/stdc++.h>
     2 const int maxn = 1000035;
     3 
     4 int n,sval,tval;
     5 char s[maxn],t[maxn];
     6 
     7 int calc(char *s)
     8 {
     9     int i = 0, j = 1, k = 0;
    10     while (i<n && j<n && k<n)
    11     {
    12         if (s[(i+k)%n]==s[(j+k)%n]) k++;
    13         else{
    14             if (s[(i+k)%n] > s[(j+k)%n])
    15                 i += k+1;
    16             else j += k+1;
    17             if (i==j) i++;
    18             k = 0;
    19         }
    20     }
    21     return std::min(i, j);
    22 }
    23 int main()
    24 {
    25     scanf("%s%s",s,t);
    26     n = strlen(s);
    27     sval = calc(s), tval = calc(t);
    28     bool fl = 1;
    29     for (int i=0; i<n; i++)
    30         if (s[(i+sval)%n]!=t[(i+tval)%n]){
    31             fl = 0;
    32             break;
    33         }
    34     if (!fl) puts("No");
    35     else{
    36         puts("Yes");
    37         for (int i=sval; i<sval+n; i++)
    38             putchar(s[i%n]);
    39         putchar('
    ');
    40     }
    41     return 0;
    42 }

    END

  • 相关阅读:
    Java设计模式——单例模式
    关于 "static" 关键字的那点事
    安卓 修改系统时间
    android sdk 5.0下载步骤
    Android开发中调用系统窗口的方法
    Eclipse 导入已有工程时.classpath和.project文件拒绝访 ...
    Android开发错误总结
    CursorIndexOutOfBoundsException
    html移动端适配方案rem
    pc端和移动端的viewport 以及 像素的含义
  • 原文地址:https://www.cnblogs.com/antiquality/p/9275322.html
Copyright © 2020-2023  润新知