暑期个人赛--第十一场--B(字符串哈希 Karp-Rabin)

时间限制 10000 ms  内存限制 65536 KB

题目描述

田田被老师要求背诵一个字符串,田田刚刚背了一个子串,说他记性差他还不承认,背下这个子串后却忘了这个子串是从哪里开始的。
现在田田把这个字符串给你,并且让你告诉他至少一次背多长的子串才不可能产生歧义,即不存在另一个子串与它相等

输入格式

输入仅一行,即要求田田背诵的字符串
长度<=10^6

输出格式

输出一行,即不产生歧义串的最小串长

输入样例

abcdabcd

输出样例

5

赛中提交:NULL


赛后AC:YES


反省:

赛后早上起来三十分钟敲完一遍AC....

哭晕在厕所......

比赛中的时候其实也把代码给敲了出来了,

但是一看题目意思觉得不对,以为是“求出一个绝对不会有重复子串的长度”

而自己苦思冥想也觉得,这个题意的话必须得要n^3

然后就一直卡着卡了一个小时....

结果出来后问翔他告诉我题意应该是“找出一个没有其他子串与他相同的子串,并输出他的长度”

..............................................................

我现在还是觉得题意应该是前一种...



下面是AC代码

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <memory.h>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <numeric>
#include <functional>
#define maxn 1000005
#define mod 100007
 
using namespace std;
typedef unsigned long long ll;
char a[maxn];
ll h[maxn];
 
int main()
{
    scanf("%s",a);
    int slen=strlen(a);
    memset(h,0,sizeof(h));
 
    h[0]=a[0];
    for(int i=1;i<slen;i+=1){
        h[i]=h[i-1]*mod+a[i];
    }
 
    for(int l=1;l<=slen;l+=1){
        ll base=1;
        for(int j=0;j<l;j+=1){
            base*=mod;
        }
 
        ll tmp1=0,tmp2=0;
        bool flag=true;
        tmp1=h[l-1];
        tmp2=tmp1%mod;
        vector<ll> g[mod];
        g[tmp2].push_back(tmp1);
        for(int i=0;i+l<slen;i+=1){
            tmp1=h[i+l]-h[i]*base;
            tmp2=tmp1%mod;
 
            if(g[tmp2].empty()){
                g[tmp2].push_back(tmp1);
            }
            else{
                int sz=g[tmp2].size();
                int j=0;
                for(;j<sz;j+=1){
                    if(g[tmp2][j]==tmp1) break;
                }
 
                if(j==sz){
                    g[tmp2].push_back(tmp1);
                }
                else{  //若有重复,则直接跳出i的循环,结束当前次l的循环
                    flag=false;
                    break;
                }
            }
        }
        if(flag){
            printf("%d\n",l);
            break;
        }
    }
 
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值