hdu5422 最大表示法+KMP

#include <iostream>
#include <algorithm>
#include <string.h>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn=20005;
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 s2[maxn*2];
char s3[maxn];
int F[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 ans=0;
     for(int i=0; i<n; i++)
     {
         while(j&&P[j]!=T[i]) j=f[j];
         if(P[j]==T[i])j++;
         if(j==m){
            ans=max(ans,i-m+1);
            j=f[j];
         }
     }
     return ans;
}
int main()
{
    int cas;
    scanf("%d",&cas);
    for(int cc=1; cc<=cas; cc++)
        {
             int n;
             scanf("%d",&n);
             scanf("%s",s);
             int d1=MaxRepresstation(s,n);
             for(int i=0; i<n;i++)
                s2[i]=s[n-1-i];
             int d2=MaxRepresstation(s2,n);
             for(int i=0; i<n; i++)
                {
                    s3[i]=s2[(d2+i)%n];
                    s2[i+n]=s2[i];
                }
             d2=find(s2,s3,F,n*2-1,n);
             d2 = n-1-d2;
             int f=-1,ans=-1;
             for(int i=0; i<n; i++)
                {
                     int x1=(d1+i)%n,x2=(d2-i+n)%n;
                     if(s[x1]==s[x2])continue;
                     if(s[x1]>s[x2]){
                        ans=d1; f=0; break;
                     }else{
                        ans=d2; f=1; break;
                     }
                }
             if(f==-1){
                 if(d1<=d2){
                    ans=d1; f=0;
                 }else{
                    ans=d2; f=1;
                 }
             }
             printf("%d %d\n",ans+1,f);
        }

    return 0;
}
时间: 2024-11-08 06:22:39

hdu5422 最大表示法+KMP的相关文章

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

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

【HDU - 5442】Favorite Donut 【最大表示法+KMP/后缀数组】

题意 给出一个长度为n的环状由小写字母组成的序列,请找出从何处断开,顺时针还是逆时针,使得字典序最大.如果两个字符串的字典序一样大,那么它会选择下下标最小的那个.如果某个点顺时针逆时针产生的字典序大小相同,那么优先选择顺时针的. 这个题用最大表示法+KMP很容易解决.因为最大表示法找到的是下表最小的那个字典序最大的字符串,所以正向的时候最大表示法找出来的就直接是答案,关键是逆时针的时候.我们将字符串翻转以后用最大表示法找到那个字符串s2,然后用KMP算法在翻转*2后的串中找出最后面的那个s2,这

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

HDU 5442——Favorite Donut——————【最大表示法+kmp | 后缀数组】

Favorite Donut Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1702    Accepted Submission(s): 430 Problem Description Lulu has a sweet tooth. Her favorite food is ring donut. Everyday she buy

回朔法/KMP算法-查找字符串

回朔法:在字符串查找的时候最容易想到的是暴力查找,也就是回朔法.其思路是将要寻找的串的每个字符取出,然后按顺序在源串中查找,如果找到则返回true,否则源串索引向后移动一位,再重复查找,直到找到返回true,或者源串查找完也没有找到返回false:这种方法简单粗暴,但思路清晰.又因为每次查找失败,源串需要回到起始位置的下一个位置开始查找,所以该算法也称为回朔法. KMP算法:先对要查找的字符串进行分析,找出其中重复的子字符串.然后将目标串与源串比较,一旦比较失败,则不用回朔,而是根据目标串子串的

hdu3374 String Problem(最小值表示法 + KMP)

题意 给一个循环串,从某个点开始会得到一个字典序最小的串,从某个点开始会得到一个字典序最大的串,求这两个点的下标,以及其出现的次数. 传送门 思路 最小/大表示法求下标,kmp求出现次数. 最小/大表示法 Code #include <cstdio> #include <cstring> using namespace std; const int maxn = 1e6+10; int nxt[maxn], l; char str[maxn<<1]; void getN

hdu 5442 Favorite Donut 最大表示法+KMP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5442 题意: 有一个由小写字母组成的字符串(长度为n),首尾相接,求顺时针转和逆时针转的情况下,长度为n的最大字典序的字符串的首位的位置. 如果顺时针和逆时针求得的字符串相同,则选择开始位置较前的,如果开始位置也相同,则选择顺时针的. 如abcd,那么顺时针可以是abcd,bcda,cdab,dabc.逆时针可以是adcb,dcba,cbad,badc. 思路: 顺时针的情况下,直接求最大字典序的位

kuangbin专题十六 KMP&amp;&amp;扩展KMP HDU3347 String Problem(最小最大表示法+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 lexicograp

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 < le