zoukankan      html  css  js  c++  java
  • 项链(最小表示法)

    题目

    题目

    思路

    看到这道题目我脑子里面第一个闪过的是KMP,但是看到第二问我就发现竟然是我不会的最小表示法。

    首先明确一个思路,如果对于两个东西我们要确定是否相同,最好的方法就是确定一个最小的东西判断相等,例如在AcWing 156. 矩阵 中就是最小的浏览顺序,而这里则是最小的字典序,所以我们不难想到最小表示法。

    什么?你说我总是讲的不好,我也没打算讲啊,这个算法OIwiki讲的挺好的,我就只做一些注释吧以及答疑吧。

    首先,暴力是我们每次比较(i)(j)开始的循环同构,把当前比较到的位置记作 ,每次遇到不一样的字符时便把大的跳过,最后剩下的就是最优解。

    int k = 0, i = 0, j = 1;
    while (k < n && i < n && j < n) {
      if (sec[(i + k) % n] == sec[(j + k) % n]) {
        ++k;
      } else {
        if (sec[(i + k) % n] > sec[(j + k) % n])
          ++i;
        else
          ++j;
        k = 0;
        if (i == j) i++;
      }
    }
    i = min(i, j);
    

    但是这个很明显在(aaaaa...b)时炸了,这个算法是(O(n^2))的。

    但是,我们可以优化!

    在这里插入图片描述

    int k = 0, i = 0, j = 1;
    while (k < n && i < n && j < n) {
      if (sec[(i + k) % n] == sec[(j + k) % n]) {
        k++;
      } else {
        sec[(i + k) % n] > sec[(j + k) % n] ? i = i + k + 1 : j = j + k + 1;
        if (i == j) i++;
        k = 0;
      }
    }
    i = min(i, j);
    

    至于正确性吗,没优化的肯定是对的,优化并没有改变正确性,所以也是对的,没有毛病。

    问题一

    为什么是最后是选择(min(i,j))呢?

    首先看看退出的条件,那么在(i,j)跳出(n)的范围是,很明显(min)会选另外一个,但是(k=n)时呢?说明两个都是最小表示,随便选一个都可以。

    问题二

    (k=n)是个什么情况?

    说明同时有两个位置都是最小表示法,那么这个字符串肯定是由一个循环节循环组成的。

    有人会问会不会是(n)个循环节加上半个循环节呢?

    不会的,你画个图就会发现这样子的话(k)是不可能等于(n)的。

    在这里插入图片描述

    代码

    #include<cstdio>
    #include<cstring>
    #define  N  2100000
    using  namespace  std;
    char  a[N],b[N];
    int  n;
    int  zxbsf(char  *s)//求最小表示法的位置
    {
    	int  i=1,j=2,k=0;
    	while(i<=n  &&  j<=n  &&  k<n)
    	{
    		if(s[i+k]==s[j+k])k++;
    		else
    		{
    			if(s[i+k]>s[j+k])i=i+k+1;
    			else  j=j+k+1;
    			if(i==j)j++;
    			k=0;
    		}
    	}
    	return  i<=n?i:j;//其实和min大同小异。
    }
    int  main()
    {
    	scanf("%s",a+1);scanf("%s",b+1);n=strlen(a+1);
    	for(int  i=2*n;i>n;i--)a[i]=a[i-n],b[i]=b[i-n];//复制一份
    	int  x=zxbsf(a),y=zxbsf(b);
    	int  t=0;
    	for(int  i=0;i<n;i++)
    	{
    		if(a[x+i]!=b[y+i])
    		{
    			t=1;
    			break;
    		}
    	}
    	if(t==1)printf("No
    ");
    	else
    	{
    		printf("Yes
    ");
    		for(int  i=0;i<n;i++)printf("%c",a[x+i]);
    		printf("
    ");
    	}
    	return  0;
    }
    
  • 相关阅读:
    idea + springboot 的java后台服务器通过小米推送
    python编程之禅
    温故而知新-MySQL高级编程
    温故而知新-mysql的一些语法show,describe,explain,fulltext
    温故而知新-PHP文件操作函数
    温故而知新-正则单词和strlen
    php使用tcpdf实现在线PDF功能
    温故而知新-array_walk和sizeof和array_count_values()和extract()
    温故而知新-strtok函数
    mysql中的blob和text区别
  • 原文地址:https://www.cnblogs.com/zhangjianjunab/p/13383817.html
Copyright © 2011-2022 走看看