zoukankan      html  css  js  c++  java
  • 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

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

    题解:我们把得到的串double一下(比如s=aa double之后 s=aaaa),然后对double之后得到的串做一个次扩展kmp,然后便利得到的Next数组。如果公共前缀匹配>=原串长度则e++,对于公共前缀小于原串长度的,我们去比较失配的第一位就可以了。再就是去重的问题,这个要注意!如果原串可以由更小的串重复得到,那我们计算的结果就有很多重复的。

    (注意double 以及去重两个操作的使用)

    ac代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #define mt(a) memset(a,0,sizeof(a))
    using namespace std;
    typedef long long ll;
    const ll mod=1e9+7;
    int extend[200001];
    int Next[200001];
    int min(int x,int y)
    {
        if(x>y) return y;
        return x;
    }
    int knext[200005];
    void getknext(char s[],int len)
    {
        mt(knext);
        int i=0;
        int j=-1;
        knext[i]=j;
        while(i<len)
        {
            if(j==-1 || s[i]==s[j]) knext[++i]=++j;
            else j=knext[j];
        }
    }
    void getNext(char t[],int len)
    {
        mt(Next);
        //ll len=strlen(t);
        Next[0]=len;
        int a,p;
        a=1;
        while( a<len && t[a]==t[a-1]) a++; // 求出长度为1的时候 解为多少
        Next[1]=a-1;
        a=1;
        for(int i=2;i<len;i++) // 后续的按照算法来就好
        {
            p=a+Next[a]-1;
            if((i-1)+Next[i-a] < p ) Next[i]=Next[i-a];// 第一种情况 没有超过等于的部分
            else // 超过的话就不好直接用next的定义 需要后续的遍历
            {
                ll j = (p - i + 1) > 0 ? (p - i + 1) : 0;
                while(i + j < len && t[i+j] == t[j]) j++;
                Next[i]=j;
                a=i;
            }
        }
    }
    char s[2000005];// s->exkmp t->Next
    int main()
    {
        int Case;
        scanf("%d",&Case);
        for(int z=1;z<=Case;z++)
        {
            scanf("%s",s);
            int len=strlen(s);
            int j=0;
            int l,e,g;
            getknext(s,len);
            int temp=len-knext[len]; // 最小重复长度
            if(len%temp) temp=1;
            else temp=len/temp;
    
            for(int i=0;i<len;i++)
            {
                s[len+i]=s[i];
            }
            getNext(s,2*len);
            l=e=g=0;
            for(int i=0;i<len;i++)
            {
                if(Next[i]>=len) e++;
                else
                {
                    int temp=i+Next[i];// postion of not match
                    if(s[temp]<s[Next[i]]) l++;
                    else if(s[temp]>s[Next[i]])g++;
                }
            }
            printf("Case %d: %d %d %d
    ",z,l/temp,e/temp,g/temp);
        }
        return 0;
    }
  • 相关阅读:
    macOS 上配置 Lua
    Oracle.ManagedDataAccess.dll
    offer
    Costura.Fody
    日志系统
    实战框架ABP
    什么是算法?
    HTTP状态码->HTTP Status Code
    How to untar a TAR file using Apache Commons
    python实践3:cursor() — 数据库连接操作
  • 原文地址:https://www.cnblogs.com/z1141000271/p/7406348.html
Copyright © 2011-2022 走看看