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;
}