• Hidden (NOIP模拟赛)(字符串模拟QAQ)


    原题传送门

    神奇的题目诶

    原来以为字符串比较一定要O(NlogN)

    结果发现可以均摊O(N)

    首先我们来讲一讲原理

    我们有3个指针i,j,k

    i=0,j=1,k=0

    一开始我们不断对k+1直到找到ch[i+k]!=ch[j+k]

    那么我们进行判断 如果ch[i+k]>ch[j+k]

    那么假设在ch[i]与ch[j]之前的字符串相同,而且我们已知ch[i+1]~ch[i+k-1]与ch[j+1]~ch[j+k-1]的字符串相同,

    比较到ch[i+k]与ch[j+k]时,我们会发现ch[j+k]比ch[i+k]更优

    所以以ch[i+1]~ch[i+k]为首的字符串一定不是最优解(因为ch[i+k]>ch[j+k]而前面的字符串相同)

    所以我们更新i+=k+1;同理,如果ch[j+k]>ch[i+k],j+=k+1;

    由于我们最终一定有一个指针超过总长N

    所以输出i,j的最小值即可。

    但是注意:本题有3个细节:

    1、假若i与j重合,那么比较无法继续,所以if(i==j)j++;

    2、每次更新指针后要清零重新开始判断

    3、由于比较时有可能比较整个字符串,所以要将原字符串复制一遍

    时间复杂度均摊O(n)

    下面贴代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    char ch[10000001];
    int ans=0,n;
    int work()
    {
        int i=0,j=1,k=0;
        while(i<n&&j<n)
        {
            k=0;
            while(ch[i+k]==ch[j+k]&&k<n)k++;
            if(k==n)break;
            if(ch[i+k]>ch[j+k])i+=k+1; else j+=k+1;
            if(i==j)++j; 
        }
        return min(i,j);
    }
    int main(){
    //    freopen("hidden.in","r",stdin);
    //    freopen("hidden.out","w",stdout);
        scanf("%d",&n);
        scanf("
    ");
        for(int i=0;i<n;i++)
        {
            scanf("%c",&ch[i]);
            if((i+1)%72==0)scanf("
    ");    
        }
        for(int i=n;i<=2*n-1;i++)
        ch[i]=ch[i-n];
        ans=work();
        printf("%d
    ",ans);
    //    fclose(stdin);
    //    fclose(stdout);
    } 
  • 相关阅读:
    DNS正向解析实现
    基于bind软件部署DNS服务器
    DNS解析工具使用案例
    DNS服务工作原理
    3
    .deb/.whl/.tgz/.tar/gz软件包安装方式(Ubuntu)
    博客系列目录
    Databricks 第3篇:pyspark.sql 通过JDBC连接数据库
    Databricks 第2篇:pyspark.sql 简介
    数据预处理 第4篇:数据预处理(sklearn 插补缺失值)
  • 原文地址:https://www.cnblogs.com/ghostfly233/p/6897532.html
Copyright © 2020-2023  润新知