• 字符串最大最小表示法


    什么是循环字符串的最小表示法

    就是对于一个字符串来说,其同构字符串中字典序最小的一个

    比如说:S = bacd,则其同构字符串有 acdb、cdba、dbac,其中acdb事S串的最小表示法,因为其字典序最小

    如何求字符串的循环同构的最小表示

    暴力的方法是,你将所有的同构都写出来,如何拍个序,输出第一个就可以,但是这样复杂度很高,没得做

    所以我们可以这样做:

      用两个指针来求,i指向最小表示的位置,j为比较指针,最终输出i,即位最小的开头位置
    令i = 0,j = 1.
      如果S[i] > S[j]	说明当前i指向的位置一定不是最小表示的起点位置,j比i小,所以j相比i来说可以是最小的起点,所以修改i的值为j,再让j++
      如果说S[i] < S[j]说明当前j指向的位置一定不是最小表示的起点位置,所以让j++
      如果说S[i] = S[j],就需要在此基础上进行接下来的比较,此时需要保持i和j的位置不变,比较后面的元素,所以需要一个新的变量k来代替ij移动,达到比较的目的
      比较S[i + k]与S[j + k],如果S[i + k] = S[j + k],则让k++,继续比下去
      如果S[i + k] < S[j + k],则k++,需要继续比下去
      如果S[i + k] > S[j + k],说明i位置开头的字符串并不是最小表示,j位置开头的字符串是比他小的,所以让i = j,j++
      记得每次比较完S[i + k]与S[j + k]不同时要将k赋值为0
     最后返回i的位置即可
    

    这样的方法也不是最优解,面对aaaaaaaaaab这类的毒瘤数据,就会被卡的死死的,因为i的指针每次只会移动1个方位,时间复杂度也很高

    所以,还需要进行优化:

    对于S[i + k] < S[j + k]时,说明j不是最小表示,那么我们就可以移动j = j + k + 1;同样的,对于S[i + k] > S[j + k]时,说明i不是最小表示,就让i = i + k + 1。最后返回i与j中最小的值即可(其实返回i就行了,能过,但是保险起见还是返回最小值叭

    为什么呢?

    拿S[i + k] < S[j + k]来说叭,其 j 到 k 中间位置的任意位置为起点都会大于以i为起点的,因为从i开头和从j开头走的前k个位置的值是相等的,所以可能的小的位置是在j + k + 1后面的

    代码实现

    int getmin(string s)
    {
        ll m = s.size();
        int i = 0, j = 1, k = 0;
        while (i < m && j < m && k < m) {
            int t = s[(i + k) % m] - s[(j + k) % m];
            if(t == 0)k++;
            else
            {
                if(t > 0)i += k + 1;
                else j += k + 1;
                if(i == j) j++;
                k = 0;
            }
        }
        return min(i, j);
    }
    

    例题:

    How many

    题意:

    给你一堆字符串,问你非同构字符串有几个

    思路:

    对每个字符串都进行求最小表示法,将其塞到set中去重

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define MAX 100000 + 5
    typedef  long long ll;
    map<string,int>mp;
    set<string>se;
    void getmin(string ss, ll m)
    {
        int i = 0, j = 1, k = 0, t;
        while (i < m && j < m && k < m) {
            t = ss[(i + k) % m] - ss[(j + k) % m];
            if(t == 0)
                k++;
            else
            {
                if(t > 0) i += k + 1;
                else j += k + 1;
                if(i == j) j++;
                k = 0;
            }
        }
        int a = min(i, j);//取最小值
        string sss = "";
        for(int p = 0; p < m; p++)//字符串拼接,有个函数来着,但是我也不知道为什么用不了
        {
            sss += ss[(p + a) % m];
        }
        se.insert(sss);
    }
    int main()
    {
        int n;
        string s;
        while (cin>>n) {
            se.clear();//记得清0
            for(int i = 1; i <= n; i++)
            {
                cin>>s;
                ll m = s.size();
                getmin(s, m);
            }
            cout<<se.size()<<endl;
        }
    }
    

    最大表示法

    int getmin(string s)
    {
        ll m = s.size();
        int i = 0, j = 1, k = 0;
        while (i < m && j < m && k < m) {
            int t = s[(i + k) % m] - s[(j + k) % m];
            if(t == 0)k++;
            else
            {
                if(t > 0)j += k + 1;
                else i += k + 1;
                if(i == j) j++;
                k = 0;
            }
        }
        return min(i, j);
    }
    

    就将else里面的那两个换个位置

    不是所有的牛奶都叫特仑苏,也不是所有的人都叫猪猪
  • 相关阅读:
    java将一个或者多个空格进行分割
    Oracle decode()函数
    javascript 匿名函数和模块化
    javascript Math函数
    javascript 数组Array排序
    jQuery 获取屏幕高度、宽度
    fastJson 转换日期格式
    QNX Development Tools Based on Eclipse IDE
    Eclipse equinox implementation of OSGi
    Eclipse SWT
  • 原文地址:https://www.cnblogs.com/chelsea0901/p/14400929.html
Copyright © 2020-2023  润新知