• HDU 4333 Contest 4


    一开始就想到了扩展KMP,因为只有扩展KMP才是处理后缀的。但忽然短路以为扩展KMP求的是最长公共后缀,囧。。。。又浪费了很多时间,都是对这个算法练得不多

    再看那个扩展KMP算法之后,就很确定要的就是这个算法了。嗯,如果直接用扩展KMP,是会超时的。后来看了别人一个很巧妙的处理,把一个串复制一下两个串拼起来,再求扩展KMP。天才的做法啊。。。

    还需要考虑一个问题,就是判重。这个真心不懂,总觉得和循环有点关系,但却想不到什么好方法。好吧,其实这个算法我也懂的,但很久没用过了,用KMP求循环节。当这个串是循环的,就代表有重复了。。。

    #include <iostream>
    #include <cstring>
    #include <string.h>
    #include <algorithm>
    #include <cstdio>
    
    using namespace std;
    
    char str1[200010],str2[100010];
    int next[100010],extand[200010];
    int knext[100010];
    
    void getnext(char *T){// next[i]: 以第i位置开始的子串 与 T的公共前缀 
         int i,length = strlen(T);
         next[0] = length;
         for(i = 0;i<length-1 && T[i]==T[i+1]; i++);
              next[1] = i;
              int a = 1;
              for(int k = 2; k < length; k++){
                      int p = a+next[a]-1, L = next[k-a];
                      if( (k-1)+L >= p ){
                           int j = (p-k+1)>0? (p-k+1) : 0; 
                           while(k+j<length && T[k+j]==T[j]) j++;// 枚举(p+1,length) 与(p-k+1,length) 区间比较 
                           next[k] = j, a = k;
                      } 
                      else next[k] = L;
             } 
    }
    void getextand(char *S,char *T){
       memset(next,0,sizeof(next)); 
             getnext(T); 
             int Slen = strlen(S), Tlen = strlen(T), a = 0;
             int MinLen = Slen>Tlen?Tlen:Slen;
             while(a<MinLen && S[a]==T[a]) a++;
             extand[0] = a, a = 0;
             for(int k = 1; k < Slen; k++){
                  int p = a+extand[a]-1, L = next[k-a];  
                  if( (k-1)+L >= p ){
                       int j = (p-k+1)>0? (p-k+1) : 0; 
                       while(k+j<Slen && j<Tlen && S[k+j]==T[j] ) j++; 
                       extand[k] = j;a = k; 
                  } 
                  else extand[k] = L;         
             }
    }
    
    void Getnxt(char *S){
        knext[0]=-1;
        int i=1,j=0;
        int len=strlen(S);
        while(i<len){
            if(S[i]==S[j]||j==-1){
                i++;
                j++;
                knext[i]=j;
            }else{
                j=knext[j];
            }
        }
    }
    
    int main(){
        int T,le,equ,ga;
        scanf("%d",&T);
        int kase=0;
        while(T--){
            cin>>str2;
            memcpy(str1,str2,sizeof(str2));
            strcat(str1,str2);
            getextand(str1,str2);
            le=equ=ga=0;
            int len=strlen(str2);
            for(int i=len-1;i>=0;i--){
                if(extand[i]>=len)
                equ++;
                else{
                    if(str1[i+extand[i]]<str2[extand[i]])
                    le++;
                    else ga++;
                }
            }
            Getnxt(str2);
            int qt=1;
            len=strlen(str2);
            int t=len-knext[len];
            if(len%t==0){
                qt=len/t;
            }
            printf("Case %d: %d %d %d
    ",++kase,le/qt,equ/qt,ga/qt);
        }
        return 0;
    }
    

      

  • 相关阅读:
    02 序列模型问题
    02 序列模型问题
    04 电路交换
    31 路由算法.md
    NumPy入门教程
    有穷自动机
    上下文无关语法
    基本乐理
    正则表达式
    【OpenCV入门教程之七】 玩转OpenCV源代码:生成OpenCV工程解决方案与OpenCV源码编译(转)
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4115293.html
Copyright © 2020-2023  润新知