zoukankan      html  css  js  c++  java
  • 【暖*墟】 #字符串# 循环同构串的最小表示法

    循环字符串的最小表示法,即:

    对于一个字符串S,求S的循环的同构字符串S’中字典序最小的一个。

    思路:首先把S复制一份接在它的结尾,得到新串SS。

    那么每个循环串可以表示为SS[ i ~ i+n-1 ](记为b[ i ])

    比较 b[ i ] 和 b[ j ] 。如果 i+k位 > j+k位,则 b[ i ] 一定不是最小同构串。

    还可以得知:b[ i+1 ] ~ b[ i+k ] 也同样不是最小同构串

    因为对于 1<=p<=k ,存在一个比其更小的 b[ j+p ] 。

    所以,b[ i+1 ] ~ b[ i+k ] 可以直接跳过。

    // ↓↓↓ 求出最小同构串的起始位置

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    #include <stack>
    #include <queue>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    
    //循环同构串的最小表示法(kmp思想)
    
    char s[2000005];
    
    int main(){
        scanf("%s",s+1); 
        int n=strlen(s+1);
        for(int i=1;i<=n;i++) s[n+1]=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; //s只由一个字符构成
            if(s[i+k]>s[j+k]){ //i位置开头已经不可能是最小
                i=i+k+1; //跳过i~i+k
                if(i==j) i++; //**特判情况**
            } else{ //j位置开头已经不可能是最小
                j=j+k+1; //跳过j~j+k
                if(i==j) j++;
            }
        } 
        int ans=min(i,j); //最后一次比较中,答案相对大的那一个被+1
        //↑↑↑那么位置较小的就是最小表示的起点位置
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    正则表达式 UBB 实例
    ThinkSNS1.6 群组邀请好友 通知页面,出现同意,忽略功能
    netbeans 自己常用的快捷键
    Windows下安装PEAR, PHPUnit成功
    PHP XML 的 DOMDocument 读取功能
    PHP XML 的 DOMDocument 创建内容
    使用 JSON 进行数据传输
    Jquery操作select
    去除VMWare Beep(VMWare 声音|嘟)
    一步步创建 边栏 Gadget(二)
  • 原文地址:https://www.cnblogs.com/FloraLOVERyuuji/p/9337010.html
Copyright © 2011-2022 走看看