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;
    }
    
  • 相关阅读:
    【codecombat】 试玩全攻略 第九关 循环又循环
    【codecombat】 试玩全攻略 第十三关 已知敌人
    【codecombat】 试玩全攻略 第十一关 再次迷宫经历
    【codecombat】 试玩全攻略 第六关 cell commentary
    【codecombat】 试玩全攻略 第八关 火舞
    【codecombat】 试玩全攻略 第十二关 恐惧之门
    【codecombat】 试玩全攻略 第十四关 已知敌人
    苹果apns推送总结
    Xcode 提升速度小技巧
    UITextField 限制输入字数
  • 原文地址:https://www.cnblogs.com/zhangjianjunab/p/13383817.html
Copyright © 2011-2022 走看看