HDU 4333 扩展KMP

点击打开链接

题意:一个数字,依次将第一位放到最后一位,问小于本身的数的个数及等于本身的个数和大于本身的个数,但是要注意重复的不再计算

思路:用扩展KMP我们可以处理,先将串复制到后面一次,然后求扩展KMP,那么我们如何比较呢,如果extand[i]的值大于串的长度len,说明我以i为开头的串和原串的匹配大于len,也就说明这个串和原串相等,接下来就是另外两种情况,若extand[i]匹配到了第三位,那么久比较原串的第三位和以i开始的第三位即可,比较过后,处理重复的串,用KMP即可处理,如果串是一个以长度为len1的子串重复得来,那么最后结果便全部除以len1,画一下就一目了然了

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=200010;
int Next[maxn],extand[maxn];
char T[maxn];
void makenext(int m){
    int i=0,j=-1;
    Next[i]=-1;
    while(i<m){
        if(j==-1||T[i]==T[j])
            Next[++i]=++j;
        else j=Next[j];
    }
}
void GetNext(const char *T){
     int len=strlen(T),a=0;
     extand[0]=len;
     while(a<len-1&&T[a]==T[a+1]) a++;
     extand[1]=a;
     a=1;
     for(int k=2;k<len;k++){
         int p=a+extand[a]-1,L=extand[k-a];
         if((k-1)+L>=p){
             int j=(p-k+1)>0? (p-k+1):0;
             while(k+j<len&&T[k+j]==T[j]) j++;
             extand[k]=j;
             a=k;
         }
         else extand[k]=L;
     }
}
int main(){
    int TT,t=1;
    scanf("%d",&TT);
    while(TT--){
        scanf("%s",T);
        int len=strlen(T);
        makenext(len);
        int k=len-Next[len];
        int tt;
        if(len%k==0) tt=len/k;
        else tt=1;
        for(int i=0;i<len;i++) T[len+i]=T[i];
        GetNext(T);
        int L=0,E=0,G=0;
        for(int i=0;i<len;i++){
            if(extand[i]>=len) E++;
            else if(T[extand[i]]>T[i+extand[i]]) L++;
            else if(T[extand[i]]<T[i+extand[i]]) G++;
        }
        printf("Case %d: %d %d %d\n",t++,L/tt,E/tt,G/tt);
    }
    return 0;
}
时间: 2024-10-29 10:45:46

HDU 4333 扩展KMP的相关文章

hdu 4333 扩展kmp+kmp重复字串去重

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333 关于kmp next数组求最短重复字串问题请看:http://www.cnblogs.com/z1141000271/p/7406198.html 扩展kmp请看:http://www.cnblogs.com/z1141000271/p/7404717.html 题目大意:一个数字,依次将第一位放到最后一位,问小于本身的数的个数及等于本身的个数和大于本身的个数,但是要注意重复的不再计算 题解:

HDU 3336 扩展kmp

题目大意: 找到字符串中所有和前缀字符串相同的子串的个数 对于这种前缀的问题,通常通过扩展kmp来解决 其实吧这是我第一次做扩展kmp的题目,原来确实看过这个概念,今天突然做到,所以这个扩展kmp的模板是做到这道题直接copy的 这里用扩展kmp很好解决问题,_next[i],表示第i位开始所能匹配到的最大公共前缀长度,比如说这个长度为4,那么说明前缀1,2,3,4都出现了一次,我们只在cnt[4]++ 那么最后从n到1,逆向更新cnt[i] += cnt[i+1]即可,最后得到cnt[i]就表

HDU 2594 扩展kmp模板题

题目大意: 给定两个字符串,在第一个字符串中找到一个最大前缀作为第二个字符串的后缀 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <climits> 8 #include <cmath>

hdu 3613 扩展kmp+回文串

题目大意:给个字符串S,要把S分成两段T1,T2,每个字母都有一个对应的价值,如果T1,T2是回文串(从左往右或者从右往左读,都一样),那么他们就会有一个价值,这个价值是这个串的所有字母价值之和,如果不是回文串,那么这串价值就为0.问最多能获得多少价值?   对于我们只需要枚举扫描一遍extend数组,扫描到的当前位置之前为前半部分T1, 然后用根据extend数组可以判断T1是否是回文.那后半部分T2呢?  刚才是用S去匹配T, 如果要求后缀,只需要用T去匹配S,再得到一个数组extend2即

hdu 3613 扩展KMP运用

题意是给你一个串    只包含a-z   每个字母对应一个价值    问把他进行一次分割成两段     若其中一段是会问串  子价值为之和否则为零     问最大的价值: 先把串str1进行反转 为str2       判断s1的前i个是不是回文串   对str2(文本串)  str1(模式串)进行EKMP   只要i==extand1[len-i] 则是回文   若要判断后i个是不是回文串 则反过来把str1作文本串  str2作模式串   进行EKMP   就ok了 #include<std

HDU 6153 A Secret(扩展KMP模板题)

A Secret Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others) Total Submission(s): 2523    Accepted Submission(s): 934 Problem Description Today is the birthday of SF,so VS gives two strings S1,S2 to SF as a present,w

扩展KMP - HDU 4333 Revolving Digits

Revolving Digits Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=4333 Mean: 给你一个字符串,你可以将该字符串的任意长度后缀截取下来然后接到最前面,让你统计所有新串中有多少种字典序小于.等于.大于原串. analyse: KMP的经典题. 首先我们将原串扩展成两倍,算一遍扩展KMP(自匹配),时间复杂度O(n). 这样一来,我们就得到了eKMP[i],eKMP[i]代表s[i...len-1]与s的最长

HDU 4333 Revolving Digits 扩展KMP

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333 题意:给以数字字符串,移动最后若干位到最前边,统计得到的数字有多少比原来大,有多少和原来相同,有多少比原来的小. 思路:拓展KMP中的next数组标记的是子串和母串的公共前缀的长度,要将字符串长度变成原来二倍,这样如果变换后不是完全相同的数字也即公共前缀长度大于等于字符串长度,那么字母串公共前缀的下一位的大小比较就是题目所要求的比较.由于相同的数字串只算一次,则只要统计比较第一个"循环节"

【扩展kmp+最小循环节】HDU 4333 Revolving Digits

http://acm.hdu.edu.cn/showproblem.php?pid=4333 [题意] 给定一个数字<=10^100000,每次将该数的第一位放到放到最后一位,求所有组成的不同的数比原数小的个数,相等的个数,大的个数 [思路] 这个数很大,用字符串处理 比较两个字符串的大小,一位一位很耗时,可以求出最长公共前缀,只比较最长公共前缀后一位 每次将数的最后一位放到最后一位,如abcd变成dabc,cdab,bcda,相当于abcdabcd各个后缀的前四位 这样就变成了求abcdabc