zoukankan      html  css  js  c++  java
  • 字符串最小表示法

    给定一个环形字符串, 显然可以有 n 种表示方法, 字典序最小的就称为这个环的最小表示法。

    设 B[i] = S[i~n] + S[1~i-1], 把 S 复制一份接到它的尾部, 得到 SS, 显然 B[i] = SS[i~i+n-1]。

    假设 B[i] 与 B[j] 比较, 第一次发现不同的地方是 SS[i+k] > SS[j+k], 那么除了 B[i] 不可能是最小表示法以外, B[i+1] ~ B[i+k] 都不可能是最小表示法。

    int n = strlen(s + 1);
    for(int i=1;i<=n;++i) s[n+i]=s[i];
    int i=1, j=2, k;
    while(i<=n && j<=n) {
        for(k=0; k<n&&s[i+k]==s[j+k]; ++k);
        if(k == n) break;
        if(s[i+k] > s[j+k]) {
            i = i+k+1;
            if(i==j) ++i;
    	} else {
            j = j+k+1;
            if(i==j) ++j;
    	}
    }
    ans = min(i,j); // B[ans] 是最小表示
    

    这个其实复杂度是 O(n) 的。

    例题:项链Necklace

    显然字符串的最小表示是唯一的, 这样, 就可以给字符串做一个唯一表示。

    #include<bits/stdc++.h>
    using namespace std;
    const int L = 1000003;
    
    int n;
    char a[L*2+1], b[L*2+1];
    
    int Min(char *s) {
      for(int i=1;i<=n;++i) s[n+i]=s[i];
      int i=1, j=2, k;
      while(i<=n && j<=n) {
        for(k=0; k<n&&s[i+k]==s[j+k]; ++k);
        if(k==n) break;
        if(s[i+k]>s[j+k]) {
          i = i+k+1;
          if(i==j) ++i;
        } else {
          j = j+k+1;
          if(i==j) ++j;
        }
      }
      return min(i,j);
    }
    
    int main() {
      scanf("%s",a+1); scanf("%s",b+1); n=strlen(a+1);
      int x=Min(a);
      int y=Min(b);
      for(int i=0;i<n;++i) if(a[x+i]!=b[i+y]) {
        puts("No");
        return 0;
      }
      puts("Yes");
      for(int i=0;i<n;++i) putchar(a[x+i]);
      return 0;
    }
    
  • 相关阅读:
    2017-09-13
    JavaSE07——异常
    FastDFS入门、搭建以及应用(转载)
    Centos7安装JDK1.8
    「扫盲」 Elasticsearch(转载)
    Java06——面向对象
    Java05——数组
    Java02——基础
    spring boot 配置文件配置项 数字特殊处理问题
    java动态代理机制之自定义实现动态代理
  • 原文地址:https://www.cnblogs.com/tztqwq/p/13597708.html
Copyright © 2011-2022 走看看