hdu 3374 String Problem

点击打开链接hdu 3374

思路:求最小/最大表示+kmp匹配

分析:
1 题目要求给定一个字符串求出最小和最大表示的rank和出现的times。
2 如果直接暴力枚举n 最大10^6肯定TLE,所以这了应该要用到的是求解一个字符串的最小和最大表示,然后利用kmp去匹配查找出现的次数
3 在利用kmp匹配的时候应该要注意不能多算,比如有abcder,那么用abcder去匹配abcderabcder的时候就有两次的匹配结果,但实际上这里只有一个,所以这个地方要注意。

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;

#define MAXN 2000010

int len;
int next[MAXN/2];
char String[MAXN];
char minString[MAXN/2] , maxString[MAXN/2];
int minTimes , maxTimes;
int minRank , maxRank;

/*求最小表示的起始坐标*/
int getMin(){
   int i = 0 , j = 1 , k = 0;
   while(i+k < len && j+k < len){
      if(String[i+k] == String[j+k])
        k++;
      else{
        if(String[i+k] > String[j+k])
           i = i+k+1;
        else
           j = j+k+1;
        k = 0;
        if(i == j)/*若滑动后i == j那么j++*/
           j++;
      }
   }
   return min(i , j);
}

/*求最大表示的起始坐标*/
int getMax(){
   int i = 0 , j = 1 , k = 0;
   while(i+k < len && j+k < len){
      if(String[i+k] == String[j+k])
        k++;
      else{
        if(String[i+k] < String[j+k])
           i = i+k+1;
        else
           j = j+k+1;
        k = 0;
        if(i == j)/*若滑动后i == j那么j++*/
           j++;
      }
   }
   return min(i , j);
}

/*求出最小表示*/
void getMinString(){
   int pos = 0;
   for(int i = minRank ; i < minRank+len/2 ; i++)
      minString[pos++] = String[i];
   minString[pos] = '\0';
}

/*求出最大表示*/
void getMaxString(){
   int pos = 0;
   for(int i = maxRank ; i < maxRank+len/2 ; i++)
      maxString[pos++] = String[i];
   maxString[pos] = '\0';
}

/*求next数组*/
void getNext(char *pattern){
    int m = strlen(pattern);
    next[0] = next[1] = 0;

    for(int i = 1 ; i < m ; i++){
       int j = next[i];
       while(j && pattern[i] != pattern[j])
          j = next[j];
       next[i+1] = pattern[i] == pattern[j] ? j+1 : 0;
    }
}

/*kmp匹配找到有几个*/
int find(char *pattern){

   int count = 0;
   int m = strlen(pattern);
   int j = 0;

   for(int i = 0 ; i < len-1 ; i++){/*这里只要判断到len-1即可,这样就可以避免多算了一次*/
      while(j && pattern[j] != String[i])
          j = next[j];
      if(pattern[j] == String[i])
          j++;
      if(j == m)
          count++;
   }
   return count;
}

int main(){
   while(scanf("%s" , String) != EOF){

      int flag;
      char tmp[MAXN];
      memcpy(tmp , String , sizeof(String));
      strcat(String , tmp);
      len = strlen(String);

      /*求字符串的最小表示*/
      minRank = getMin();
      getMinString();
      getNext(minString);
      minTimes = find(minString);

      /*求字符串的最大表示*/
      maxRank = getMax();
      getMaxString();
      getNext(maxString);
      maxTimes = find(maxString);

      /*输出*/
      printf("%d %d %d %d\n" , minRank+1 , minTimes , maxRank+1 , maxTimes);
   }
   return 0;
}
时间: 2024-10-21 17:45:23

hdu 3374 String Problem的相关文章

hdu 5284 wyh2000 and a string problem

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5284 题目大意:青年理论计算机科学家wyh2000在教小学生一些基础的字符串概念. 定义一个字符串s 的子序列为将s 中一些元素删掉得到的字符串.可以删掉全部元素,可以不删,也可以只删一些. 他还教了小学生如何判断一个串是不是另一个串的子序列.比如给你一个串,要求判断wyh 是不是它的子序列,那么你只需要找一个w ,找一个y ,再找一个h ,使得w 在y 前面,y 在h 前面即可. 有一天小学生拿着

算法:HDU 4681 String (dp, LCS | 多校8)

题意 给出3个字符串A,B,C,要你找一个字符串D, 要满足下面规定 a) D是A的子序列 b) D是B 的子序列 c) C是D的子串 求D的最大长度 要注意子序列和子串的区别,子序列是不连续的,字串是连 续的 思路 由题目可知,C一定是A和B的子序列,那么先假设C在A和B中只有一个子序列,看下 面例子: abcdefdeg acebdfgh cf 可以看到"cf"在A串的[3, 6]区间 内, 在B串的[2,6]区间(黄色背景) 因为所求的C是D的子串,所以在该黄色区间内的其他字母一

算法题:HDU 1022 Train Problem I 栈

As the new term comes, the Ignatius Train Station is very busy nowadays. A lot of student want to get back to school by train(because the trains in the Ignatius Train Station is the fastest all over the world ^v^). But here comes a problem, there is

HDOJ/HDU 1022 Train Problem I(模拟栈)

Problem Description As the new term comes, the Ignatius Train Station is very busy nowadays. A lot of student want to get back to school by train(because the trains in the Ignatius Train Station is the fastest all over the world ^v^). But here comes

hdu 5427 A problem of sorting

点击打开链接 Problem Description There are many people's name and birth in a list.Your task is to print the name from young to old.(There is no pair of two has the same age.) Input First line contains a single integer T \leq 100T≤100 which denotes the numb

KMP专题【完结】

第一题 hdu 1711 Number Sequence 点击打开hdu 1711 思路: 1 kmp是用来匹配字符串,只能够匹配单一的字符串 2 kmp的算法的过程:   1:假设文本串的长度为n,模式串的长度为m:   2:先例用O(m)的时间去预处理next数组,next数组的意思指的是当前的字符串匹配失败后要转到的下一个状态:   3:利用o(n)的时间去完成匹配: 3 时间复杂度为o(n+m)即o(n): 点击查看代码 第二题 hdu 1686 oulipo 点击打开hdu 1686

hdu 1568 Fibonacci

点击此处即可传送hdu 1568 **Fibonacci** Problem Description 2007年到来了.经过2006年一年的修炼,数学神童zouyu终于把0到100000000的Fibonacci数列 (f[0]=0,f[1]=1;f[i] = f[i-1]+f[i-2](i>=2))的值全部给背了下来. 接下来,CodeStar决定要考考他,于是每问他一个数字,他就要把答案说出来,不过有的数字太长了.所以规定超过4位的只要说出前4位就可以了,可是CodeStar自己又记不住.于

【DP专辑】ACM动态规划总结

转载请注明出处,谢谢.   http://blog.csdn.net/cc_again?viewmode=list          ----------  Accagain  2014年5月15日 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间效率高,代码量少,多元性强,主要考察思维能力.建模抽象能力.灵活度. 本人动态规划博客地址:http://blog.csdn.net/cc_again/article/category/1261899 ******************

【网络爬虫】给关键字获取百度知道搜索数据的网络爬虫

转载请注明出处http://blog.csdn.net/qq_26525215 本文源自[大学之旅_谙忆的博客] 简单的通过关键字爬出百度知道的一些搜索数据. 例如问题提问时间答案文本答案时间点赞数拍砖数回答人回答人级别搜索的关键字等. 答案可以有多个每个问题有多个答案应都保存.保存数据在MySql中. 在这里需要用到一个牛人的爬虫框架 WebMagic 网址http://webmagic.io/docs/zh/ 我用的是IEDA工具建立的是Maven项目. 要搞爬虫一些基础的学习是不可少的比如