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

    我的原文链接是:http://alphaway.org/post-340.html

    有一个字符串,这个字符串的首尾是连在一起的,要求寻找一个位置,以该位置为起点的字符串的字典序在所有的字符串中中最小。

    【暴力算法】:

    O(n)的时间枚举起始位置,O(n)的时间比对字符串的字典序,总的时间复杂度是O(n*n)。

    【线性算法】:

    初始时,让i=0,j=1,k=0。

    分为三种情况

    1.如果str[i+k]==str[j+k] j++。

    2.如果str[i+k] > str[j+k] i = i + k + 1,即最小表示不可能以str[i->i+k]开头。

    3.如果str[i+k] < str[j+k] j = j + k + 1,即最小表示不可能以str[j->j+k]开头。

    那么只要循环n次,就能够判断出字符串的最小表示是以哪个字符开头。

    为什么当str[i+k] > str[j+k] i = i + k + 1,最小表示不可能以str[i->i+k]开头,让我们来举个栗子。

    如下图,当i=1,j=5,k=3时,str[i+k] > str[j+k]。

    首先有S1S2S3 == S5S6S7,S4 > S8。

    那么以字符S2开头肯定不如以字符S6开头更优,因为S4 < S8啊。

    #include <stdio.h>
    #include <string.h>
    const int N = 100000+10;
    char str[N];
    int minimalRepresentation()
    {
        int n = strlen(str);
        int i = 0,j = 1, k = 0;
        while(i<n && j<n && k<n)
        {
            int t = str[(i+k)%n] - str[(j+k)%n] ;
            if(t == 0)
                k++;
            else
            {
                if(t>0)
                    i+=k+1;
                else 
                    j+=k+1;
                if(i==j)
                    j++;
                k = 0;
            }
        }
        return i < j ? i : j;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        int n;
        while(t--)
        {
            scanf("%d",&n);
            scanf("%s",str);
            int index = minimalRepresentation();
            printf("%d
    ",index);
        }
    }
     
     
     

     

  • 相关阅读:
    类似最长递增子序,记忆化DP—— Codeforces Beta Round #4 (Div. 2 Only)D Mysterious Present
    最小逆序数对——hdu1394
    区间更新 求总区间——hdu1754
    抽象类 虚函数实现
    poj2271
    poj2246
    poj2410
    poj2567
    poj2247
    Integration Services 学习(7):包部署 (转自游子吟)
  • 原文地址:https://www.cnblogs.com/justPassBy/p/5296275.html
Copyright © 2011-2022 走看看