莫过一日曝十日寒。
问题 L: 【KMP】Radio Transmission
时间限制: 1 Sec 内存限制: 128 MB
提交: 39 解决: 10
[提交] [状态] [讨论版] [命题人:admin]
题目描述
给你一个字符串,它是由某个字符串不断自我连接形成的。但是这个字符串是不确定的,现在只想知道它的最短长度是多少。
输入
第一行给出字符串的长度L,第二行给出一个字符串,全由小写字母组成。
输出
输出最短的长度。
样例输入
复制样例数据
8
cabcabca
样例输出
3
提示
我们可以利用abc不断自我连接得到abcabcabc,读入的cabcabca是它的子串。
对于全部数据,1≤L≤106
许久不看hash都忘掉了
hash
hash一遍,然后枚举答案
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<unsigned int,unsigned int> puii;
const int maxn = 1e6+7;
const puii sup = {233,2333};
puii operator + (puii a,puii b){return make_pair(a.first+b.first,a.second+b.second);}
puii operator + (puii a,int b){return make_pair(a.first+b,a.second+b);}
puii operator - (puii a,puii b){return make_pair(a.first-b.first,a.second-b.second);}
puii operator * (puii a,puii b){return make_pair(a.first*b.first,a.second*b.second);}
puii p[maxn] = {{0,0}};
char s[maxn];
puii Pow(puii a,int b){
puii ans = {1,1};
while(b){
if(b&1)
ans = ans*a;
a = a*a;
b>>=1;
}
return ans;
}
int main()
{
int n;
scanf("%d%s",&n,s+1);
for(int i=1;i<=n;i++)
p[i] = p[i-1]*sup + s[i];
for(int len=1;len<=n;len++){
puii x = p[len];
puii cc = Pow(sup,len);
int j = len;
while(j<=n){
if(x != p[j]-p[j-len]*cc)
break;
j += len;
}
if(j>n){
j -= len;
if(j == n || p[n]-p[j]*Pow(sup,n-j) == p[n-j])
return 0*printf("%d\n",len);
}
}
return 0*printf("%d\n",n);
}
kmp
这个n-失配[n]画个图容易理解
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void GetNext(char t[],int *next,int n){
int i = 1,j = 0;
while(i<n)
(t[i]==t[j]) ? (next[i++] = ++j) :
((j == 0) ? (next[i++] = j) : (j = next[j-1]));
}
char s1[1000006];
int main()
{
int n;
scanf("%d",&n);
scanf("%s",s1);
int *next = new int[n];
GetNext(s1,next,n);
printf("%d\n",n-next[n-1]);
return 0;
}