设为首页 加入收藏

TOP

第三周训练总结(一)
2019-09-14 00:51:17 】 浏览:81
Tags:第三 训练 总结

一、KMP+最大最小值表示法

最大最小值表示法

最大最小表示法用于解决字符串的同构问题,其在复杂度为$ O(n) $的时间内求出一个字符串的所有同构串中字典序最大(小)的串的起始位置。

应用:

  • 给出$ n $个循环字符串判断有多少不同字符串:逐个用最大(小)表示法表示,然后加入 \(Set\) 去重
  • 循环字符串所有同构串中字典序最大(小)的表示:用最大(小)表示法求出起始位置,输出即可
  • 判断两个字符串是否同构:将两字符串用最大(小)表示法表示,然后逐个字符比较

原理:

设一字符串 \(S\),且 $S’ \(是\) S $的循环同构的串的最小表示,那么对于字符串循环同构的最小表示法,其问题实质是求 S 串的一个位置,从这个位置开始循环输出 \(S\),得到的 $S’ $字典序最小。

最朴素的算法是设$ i\(、\)j \(两个指针,\)i \(指向最小表示的位置,\)j $作为比较指针。

\(i=0\)\(j=1\),那么:

  • \(S[i]>S[j]\),则:\(i=j\)\(j=i+1\)
  • \(S[i]<S[j]\),则:\(j++\)
  • \(S[i]=S[j]\),则设指针 \(k\),分别从 $i $和 $j \(位置向下比较,直到\) S[i]!=S[j]$
  • \(S[i+k]>S[j+k]\),则:\(i=j\)\(j=i+1\)
  • 否则$ j++$

最后返回 $i $即可

可以看出,朴素算法在 $S[i]=S[j] \(时,\)i $的指针移动的太少了,在遇到像 $bbb…bbbbbba $这样复杂的字符串时,时间复杂度可能会退化到 \(O(n^2)\),针对这一问题加以改进可得到 \(O(n)\) 的最小表示法的算法,其核心思路是在$ S[i]=S[j]$ 时同时维护 \(i\)、$j $两个指针

同样令 \(i=0\)\(j=1\),那么:

  • \(S[i]>S[j]\),则:\(i=j\)\(j=i+1\)
  • \(S[i]<S[j]\),则:\(j++\)
  • 若$ S[i]=S[j]\(,则设指针\) k\(,分别从\) i \(和\) j $位置向下比较,直到 \(S[i]!=S[j]\)
  • \(S[i+k]>S[j+k]\),则:\(i=i+k\)
  • 否则 \(j++\)

最后返回$ i $和 $j $的小者即可

1、最小值表示法

int minmumRepresentation(char *str) //最小表示法
{
    int len=strlen(str);
    int i=0;                        //指向字符串最小的位置
    int j=1;                        //比较指针
    int k=0;            //str[i]与str[j]相等时一次移动几个
    while(i<len&&j<len&&k<len)
    {
        int temp=str[(i+k)%len]-str[(j+k)%len];//比较值的长度
        if(temp==0)
            k++;
        else
        {
            if(temp>0)              //维护i
                i=i+k+1;
            else                    //维护j
                j=j+k+1;
            if(i==j)                //相等时比较指针后移
                j++;
            k=0;
        }
    }
    return i<j?i:j;                 //返回i、j中较小的那个
}

2、最大值表示法

int maxmumRepresentation(char *str) //最大表示法
{
    int len=strlen(str);
    int i=0;                        //指向字符串最小的位置
    int j=1;                        //比较指针
    int k=0;            //str[i]与str[j]相等时一次移动几个
    while(i<len&&j<len&&k<len)
    {
        int temp=str[(i+k)%len]-str[(j+k)%len];//比较值的长度
        if(temp==0)
            k++;
        else
        {
            if(temp>0)              //维护i
                j=j+k+1;
            else                    //维护j
                i=i+k+1;
            if(i==j)                //相等时比较指针后移
                j++;
            k=0;
        }
    }
    return i<j?i:j;                 //返回两者最小值
}

HDU-3374解题思路

首先判定是否是循环串,然后用最小表示法和最大表示法来找出对应的位置,最小表示法可以找出比如一个环形的字符串,找出某个字符开始,然后这个字符串字典序最小

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define PI acos(-1.0)
#define E 1e-9
#define INF 0x3f3f3f3f
#define LL long long
const int MOD=10007;
const int N=1000000+5;
const int dx[]= {-1,1,0,0};
const int dy[]= {0,0,-1,1};
using namespace std;
int Next[N];
char str[N];
void getNext(char p[])
{
    Next[0]=-1;
    int len=strlen(p);
    int j=0;
    int k=-1;

    while(j<len)
    {
        if(k==-1||p[j]==p[k])
        {
            k++;
            j++;
            Next[j]=k;
        }
        else
        {
            k=Next[k];
        }
    }
}
int minmumRepresentation(char *str) //最小表示法
{
    int len=strlen(str);
    int i=0;
    int j=1;
    int k=0;
    while(i<len&&j<len&&k<len)
    {
        int temp=str[(i+k)%len]-str[(j+k)%len];
        if(temp==0)
            k++;
        else
        {
            if(temp>0)
                i=i+k+1;
            else
                j=j+k+1;
            if(i==j)
                j++;
            k=0;
        }
    }
    return i<j?i:j;
}
int maxmumRepresentation(char *str) //最大表示法
{
    int len=strlen(str);
    int i=0;
    int j=1;
    int k=0;
    while(i<len&&j<len&&k<len)
    {
        int temp=str[(i+k)%len]-str[(j+k)%len];
        if(temp==0)
            k++;
        else
        {
            if(temp>0)
                j=j+k+1;
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇QRowTable表格控件(四)-效率优化.. 下一篇从“HDU 2005 第几天?”谈起

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目