hdu 4821

题意:就是有一个字符串S,要求找到符合以下几种情况S的子串的个数.

情况1: 该子串的长度为L*M

请况2: 该子串的字串被分为M个,在该M个子子串中不存在相同.

(子串不同:出发的下标不同)

解题思路:

对于该问题的核心有两点:因为总串的长度比较大,所以判段字符串时否出现相同,不可能用平常的比较方法,第二如何判断两个相同的字符串到底在那个子串中。

对于第一点,我们可以用字符串hash函数来解决。

对于第二点,我们先算出下标[0,L)的所有子串的请况,那么[L,|s|- L*M]的请况可以根据之前算过的来推出。


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <map>
#include <math.h>
using namespace std;
#define MAXSZ 100010
#define MOD 100003
typedef unsigned int ul;
typedef struct node{
    node(){
        
    }
    node(ul hanum){
        //s = key;
        hashnum = hanum;
    }
   // string s;
    ul hashnum;
};
bool vis0[MAXSZ],vis1[MAXSZ];
char str[MAXSZ];
int hasharr[MAXSZ],cnt,indexs[MAXSZ];
int M,L;
node vt[MAXSZ];
vector<int>vt1[MAXSZ];
map<int,int>mp[MAXSZ];
//inline ul BKDRHash(char *str){
//    ul seed = 31; // 31 131 1313 13131  etc..
//    ul hash = 0;
//
//    while (*str)
//    {
//        hash = hash * seed + (*str++);
//    }
//
//    return (hash & 0x7FFFFFFF);
//}
void init(){
    cnt = 0;
    //memset(ff,0,sizeof(ff));
    //memset(vis2,0,sizeof(vis2));
    for(int i=0;i<MAXSZ;++i){
        if(mp[i].size()){
            mp[i].clear();
        }
    }
}
int  hashit(char *key,ul hashnum){
    int ind = hashnum%MOD;
    while(vis0[ind]){
        if(vt[ind].hashnum!=hashnum){
            ind++;
        }
//        else if(vt[ind].s!=key){
//            ind++;
//        }
        else
            break;
        if(ind==M){
           ind%=M;
        }
    }
    if(!vis0[ind]){
        //vt[ind].s = key;
        vt[ind].hashnum = hashnum;
        vis0[ind] = true;
        hasharr[cnt++] = ind;
    }
    return ind;
}
void prepro(){
    char *p0 = str;
    char *p1 = str;
    char cc;
    ul hash = 0;
    ul seed = 31;
    ul hashnum;
    ul tmphs0;
    int ind = 0,ind1 = 0;
    tmphs0 = 1;
    for(;ind<L;++ind){
        hash = hash*seed +(*p1++);
        //hash %= MOD;
        if(ind){
            tmphs0 = (tmphs0*seed);
        }
    }
    hashnum = hash&0x7FFFFFFF;
    //cc = (*p1);
    //(*p1) = 0;
    //ind = hashit(p0,hashnum);
    //(*p1) = cc;
    //vt1[ind].push_back(0);
    indexs[0] = hashnum;
    while(*p1){
        hash = ((hash - tmphs0*(*p0++)));
        hash = (hash*seed +(*p1++));
        cc = (*p1);
        ++ind1;
       // (*p1) = 0;
       // ind = hashit(p0,hash&0x7FFFFFFF);
        //(*p1) = cc;
        //vt1[ind].push_back(ind1);
        indexs[ind1] = hash&0x7FFFFFFF;
    }
    
}
int solve(){
   // memset(vis1,false,sizeof(vis1));
   // memset(vis2,false,sizeof(vis2));
    int len = (int)strlen(str);
    int ans ;
    int sz;
    int tmp0,tmp1,tmp2,tmp3,tmp4,tmp5,tmp6;
    int up = len - (L*M);
    ans = 0;
//    for(int i=0;i<cnt;++i){
//        tmp0 = hasharr[i];
//        sz = (int)vt1[tmp0].size();
//        for(int j=0;j<sz;++j){
//            for(int k=j+1;k<sz;++k){
//                tmp3 = vt1[tmp0][j];
//                tmp4 = vt1[tmp0][k];
//                tmp1 = (tmp4 - tmp3);
//                if(tmp1%L==0){
//                    tmp2 = tmp1/L;
//                    if(tmp2+1<=M){
//                        for(int h=0;h<=up;++h){
//                            if(h>tmp3)break;
//                            if((tmp3-h)%L==0&&(tmp4-h)%L==0){
//                                //tmp5 = (tmp3-h)/L+1;
//                                //tmp6 = (tmp4 - h)/L+1;
//                                
//                                if(!vis1[h]){
//                                    vis1[h] = true;
//                                    --ans;
//                                }
//                            }
//                        }
//                    }
//                }
//            }
//        }
//    }
    
    for(int i=0;i<L&&i<=up;++i){
     //int ss = 0;
        for(int k=i,j=0;j<M;++j,k+=L){
            tmp0 = indexs[k];
            if(mp[i].count(tmp0)){
                //++vis2[tmp0];
                ++mp[i][tmp0];
                //--ans;
                //break;
            }
            else {
               // ++ans;
               // ff[ss++] = tmp0;
                //++ff[i];
                //++vis2[tmp0] ;
                mp[i].insert(pair<int,int>(tmp0,1));
            }
        }
        if(mp[i].size()==M){
            ++ans;
        }
    }
    int ML = (M-1)*L;
    for(int i=L;i<=up;++i){
        tmp2 = i%L;
        tmp0 =indexs[i-L];
        --mp[tmp2][tmp0];
        //--vis2[tmp0];
        //if(!vis2[tmp0])
          
        //ff[i] = ff[i-L];
        if(!mp[tmp2][tmp0]){
            mp[tmp2].erase(tmp0);
        }
            //--ff[i];
        tmp1 = ML;
        tmp0 = indexs[i+ML];
        if(mp[tmp2].count(tmp0)){
           // ++vis2[tmp0];
            ++mp[tmp2][tmp0];
        }
        else {
           //[tmp0];
            mp[tmp2].insert(pair<int,int>(tmp0,1));
            //++ff[i];
           // ++ans;
            if(mp[tmp2].size()==M){
                ++ans;
            }
        }
    }
    return ans;
}
void clear(){
//    for(int i=0;i<cnt;++i){
//        if(vt1[i].size()){
//            vt1[i].clear();
//        }
//    }
}
int main(){
    
//    for(int i=100000;;++i){
//        bool flag = true;
//        for(int j=2;j<=sqrt(i*1.0);++j){
//            if(i%j==0){
//                flag = false;
//                break;
//            }
//        }
//        if(flag){
//            printf("%d\n",i);
//            break;
//        }
//    }
    while(scanf("%d%d",&M,&L)!=EOF){
        init();
        scanf("%s",str);
        prepro();
       int ans = solve();
        printf("%d\n",ans);
       // clear();
    }
    return  0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值