您的位置:首页 > 其它

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

2014-08-08 09:39 381 查看


480. 田田背课文

时间限制 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: