zoukankan      html  css  js  c++  java
  • [USACO5.5]Hidden Password

    题目大意:
      求字符串最小表示。

    思路:
      本来按照lbn187的课件,知道SAM可以求字符串最小表示。
      然而他并没有提供例题,就自己找了一道做。
      大体思想就是把字符串复制一遍接在后面,构建SAM,然后每次跑小的转移。
      跑n次以后就跑到了最小表示的末尾,用该状态的len值减去n就是最小表示的起始位置。
      然后交上去就MLE了。
      看了网上的题解发现求最小表示有专门的做法,也是O(n)的,还特别简单,不知道比SAM妙到哪里去了。
      核心思想就是设两个指针i和j,表示目前比较的循环串的开头位置。
      再用k表示目前比较的循环串的长度。
      当目前比较的串字典序一样大时,增加比较的长度。
      当两个不一样大时,大的那个可以直接舍去,将开头位置加上k+1,继续比较。字典序小的不变。
      一直比较到其中一个指针扫完整个字符串,这时小的那个指针就是最小表示的起始位置。

     1 #include<cstdio>
     2 #include<iostream>
     3 int n;
     4 std::string s,t;
     5 int solve() {
     6     int i=0,j=1;
     7     while(i<n&&j<n) {
     8         int k=0;
     9         while(s[(i+k)%n]==s[(j+k)%n]&&k<n) k++;
    10         if(k==n) break;
    11         (s[(i+k)%n]>s[(j+k)%n]?i:j)+=k+1;
    12         if(i==j) i++;
    13     }
    14     return std::min(i,j);
    15 }
    16 int main() {
    17     std::cin>>n;
    18     while(std::cin>>t) {
    19         s+=t;
    20     }
    21     std::cout<<solve()<<std::endl;
    22     return 0;
    23 }
  • 相关阅读:
    JS站点
    1011 World Cup Betting (20分)
    1007 Maximum Subsequence Sum (25分)(动态规划DP)
    1006 Sign In and Sign Out (25分)
    1005 Spell It Right (20分)
    1004 Counting Leaves (30分)(DFS)
    1003 Emergency (25分)(Dijkstra算法)
    1002 A+B for Polynomials (25分)
    1001 A+B Format (20分)
    canvas
  • 原文地址:https://www.cnblogs.com/skylee03/p/7526731.html
Copyright © 2011-2022 走看看