hdu3374 最大最小表示法 +kmp

#include <iostream>
#include <algorithm>
#include <string.h>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn=2000005;
int MinRepresstation(char * S, int len ) {
      int i = 0, j = 1, k = 0;
      while(i < len && j < len)
        {
            k = 0;
           while(k < len && S[(i + k)%len] == S[(j + k)%len])
            k++;
           if(k >= len)
            break;
           if(S[(i + k)%len] > S[(j + k)%len])
            i = max(i + k + 1, j + 1);
           else
            j = max(i + 1, j + k + 1);
        }
      return min(i ,j);
}
int MaxRepresstation(char * S, int len ) {
      int i = 0, j = 1, k = 0;
      while(i < len && j < len)
        {
            k = 0;
           while(k < len && S[(i + k)%len] == S[(j + k)%len])
            k++;
           if(k >= len)
            break;
           if(S[(i + k)%len] > S[(j + k)%len])
            j = max(i + 1, j + k + 1);
           else
            i = max(i + k + 1, j + 1);
        }
      return min(i ,j);
}
char s[maxn];
char s1[maxn],s2[maxn];
void getFail(char *P, int *f, int m)
{
    f[0]=0; f[1]=0;
    for(int i=1; i<m; i++)
    {
        int j=f[i];
        while(j&&P[i]!=P[j])j=f[j];
        f[i+1]=P[i]==P[j]?j+1:0;
    }
}
int find(char *T,char *P, int *f,int n, int m)
{
    getFail(P,f,m);
    int j=0;
    int num=0;
    for(int i=0; i<n-1; i++)
    {
         while(j&&P[j]!=T[i])j=f[j];
         if(P[j]==T[i])j++;
         if(j==m){
            num++; j=f[j];
         }
    }
    return num;
}
int F[maxn];

int main()
{

    while(gets(s))
        {

          int len=strlen(s);
          int d1=MinRepresstation(s,len);
          int d2=MaxRepresstation(s,len);
          for(int i = 0 ; i < len ; i ++)
            s[ i + len ] = s[ i ];
          for(int i=0; i<len; i++)
            {
                s1[i]=s[(i+d1)%len];
                s2[i]=s[(i+d2)%len];
            }
          int ans1=find(s,s1,F,len*2,len);
          int ans2=find(s,s2,F,len*2,len);
          printf("%d %d %d %d\n",d1+1,ans1,d2+1,ans2);
        }

    return 0;
}
时间: 2024-11-05 13:39:38

hdu3374 最大最小表示法 +kmp的相关文章

Hdu 5442 Favorite Donut (2015 ACM/ICPC Asia Regional Changchun Online 最大最小表示法 + KMP)

题目链接: Hdu 5442 Favorite Donut 题目描述: 给出一个文本串,找出顺时针或者逆时针循环旋转后,字典序最大的那个字符串,字典序最大的字符串如果有多个,就输出下标最小的那个,如果顺时针和逆时针的起始下标相同,则输出顺时针. 解题思路: 看到题目感觉后缀数组可以搞,正准备犯傻被队友拦下了,听队友解释一番,果断丢锅给队友.赛后试了一下后缀数组果然麻烦的不要不要的(QWQ),还是最大最小表示法 + KMP来的干净利索. 最大表示法:对于一个长度为len文本串,经过循环旋转得到长度

hdu3374 kmp+最小表示法

Give you a string with length N, you can generate N strings by left shifts. For example let consider the string "SKYLONG", we can generate seven strings: String Rank SKYLONG 1 KYLONGS 2 YLONGSK 3 LONGSKY 4 ONGSKYL 5 NGSKYLO 6 GSKYLON 7 and lexic

HDU 3374 最小/大表示法+KMP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3374 题意:给定一个串s,该串有strlen(s)个循环同构串,要求输出字典序最小的同构串的下标,字典序最小的出现次数,最大的同构串的下标,字典中最大的出现次数. 思路:对于求循环同构的字典序最小可以用最小表示法求得,最大也是一样.然后设ds为字符串s+s.然后就可以用KMP求最小串在ds出现的次数和最大串出现的次数了. #define _CRT_SECURE_NO_DEPRECATE #inclu

hdu5442(2015长春赛区网络赛1006)后缀数组+KMP /最小表示法?

题意:给定一个由小写字母组成的长度为 n 的字符串,首尾相连,可以从任意一个字符开始,顺时针或逆时针取这个串(长度为 n),求一个字典序最大的字符串的开始字符位置和顺时针或逆时针.如果有多个字典序最大的字符串,优先选择开始位置靠前的,如果开始位置相同,优先选择顺时针. 这种字符串的问题,第一反应是后缀数组,为了达到首尾相连的目的,所以先复制了一个两倍长的该字符串,然后再将串倒置,也弄成两倍长度,得到顺逆时针的两倍长的串,并对这两个字符串分别做后缀数组,得到 sa 数组(该串字典序第几小的后缀的开

String Problem hdu 3374 最小表示法加KMP的next数组

String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1492    Accepted Submission(s): 662 Problem Description Give you a string with length N, you can generate N strings by left shifts.

【KMP】【最小表示法】NCPC 2014 H clock pictures

题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1794 题目大意: 两个无刻度的钟面,每个上面有N根针(N<=200000),每个针都是相同的,分别指向Ai,Bi(360°被分成360000小份),问能否将其中一个旋转和另一个重合. 题目思路: [KMP][最小表示法] 循环同构问题.可以写KMP,我懒得写KMP了就写了循环同构的最小表示法. 首先将Ai排序,然后求差(记得取模360000,WA了一次),接下来复制一遍开始匹配. A

[coj 1353 Guessing the Number]kmp,字符串最小表示法

题意:给一个字符串,求它的最小子串,使得原串是通过它重复得到的字符串的一个子串. 思路:先求最小长度,最小循环长度可以利用kmp的next数组快速得到,求出长度后然后利用字符串最小表示法求循环节的最小表示即可. #pragma comment(linker, "/STACK:10240000") #include <map> #include <set> #include <cmath> #include <ctime> #include

hdu 3374 String Problem (kmp+最大最小表示法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3374 题目大意:输出最大和最小的是从哪一位开始的,同时输出最小循环节的个数. 这里简单介绍对字符串最小表示的方法: (1)  利用两个指针p1, p2.初始化时p1指向s[0], p2指向s[1]. (2)  k = 0开始,检验s[p1+k] 与 s[p2+k] 对应的字符是否相等,如果相等则k++,一直下去,直到找到第一个不同,(若k试了一个字符串的长度也没找到不同,则那个位置就是最小表示位置,

HDU 3374 (KMP 最小表示法)

String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2442    Accepted Submission(s): 1029 Problem Description Give you a string with length N, you can generate N strings by left shift