题目:
http://acm.hdu.edu.cn/showproblem.php?pid=4333
题意:
给出一个长度为
105
以内的没有前导
0
的数字,每次把最后一个数字移到最前面形成一个新数字,有前导
思路:
首先注意是不同的新数字,这意味着要去重。把原串复制一次接在后面形成两倍原串,然后
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N = 100000 + 10, INF = 0x3f3f3f3f;
const ull seed = 31;
ull hash_ori[N*2], seed_pow[N];
char ori[N*2], pat[N];
int Next[N], extend[N*2];
int cas = 0;
struct node
{
int x, ext;
ull val;
friend bool operator< (node a, node b)
{
return a.val < b.val;
}
}a[N];
void get_next(char *pat)
{
int len = strlen(pat);
Next[0] = len;
int k = 0;
while(k + 1 < len && pat[k] == pat[k+1]) ++k;
Next[1] = k;
k = 1;
for(int i = 2; pat[i]; i++)
{
if(i + Next[i-k] < k + Next[k]) Next[i] = Next[i-k];
else
{
int j = max(k + Next[k] - i, 0);
while(i + j < len && pat[j] == pat[i+j]) ++j;
Next[i] = j;
k = i;
}
}
}
void extkmp(char *ori, char *pat)
{
get_next(pat);
int leno = strlen(ori), lenp = strlen(pat);
int k = 0;
while(k < leno && k < lenp && ori[k] == pat[k]) ++k;
extend[0] = k;
k = 0;
for(int i = 1; ori[i]; i++)
{
if(i + Next[i-k] < k + extend[k]) extend[i] = Next[i-k];
else
{
int j = max(k + extend[k] - i, 0);
while(i + j < leno && j < lenp && ori[i+j] == pat[j]) ++j;
extend[i] = j;
k = i;
}
}
}
int main()
{
seed_pow[0] = 1;
for(int i = 1; i < N; i++) seed_pow[i] = seed_pow[i-1] * seed;
int t;
scanf("%d", &t);
while(t--)
{
scanf(" %s", pat);
int lenp = strlen(pat);
for(int i = 0; i < lenp; i++) ori[i] = ori[i+lenp] = pat[i];
ori[lenp*2] = '\0';
for(int i = 0; ori[i]; i++) hash_ori[i+1] = hash_ori[i] * seed + ori[i];
extkmp(ori, pat);
for(int i = 0; i < lenp; i++)
{
a[i].x = i; a[i].ext = extend[i];
a[i].val = hash_ori[i+lenp+1] - hash_ori[i+1] * seed_pow[lenp];
}
sort(a, a + lenp);
int ansl = 0, anse = 0, ansg = 0;
for(int i = 0; i < lenp; i++)
{
if(i == 0 || a[i].val != a[i-1].val)
{
if(a[i].ext == lenp) anse++;
else
{
if(ori[a[i].x+a[i].ext] > ori[a[i].ext]) ansg++;
else ansl++;
}
}
}
printf("Case %d: %d %d %d\n", ++cas, ansl, anse, ansg);
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 100000 + 10, INF = 0x3f3f3f3f;
char ori[N*2], pat[N];
int Next[N], extend[N*2];
int cas = 0;
void get_next(char *pat)
{
int len = strlen(pat);
Next[0] = len;
int k = 0;
while(k + 1 < len && pat[k] == pat[k+1]) ++k;
Next[1] = k;
k = 1;
for(int i = 2; pat[i]; i++)
{
if(i + Next[i-k] < k + Next[k]) Next[i] = Next[i-k];
else
{
int j = max(k + Next[k] - i, 0);
while(i + j < len && pat[j] == pat[i+j]) ++j;
Next[i] = j;
k = i;
}
}
}
void extkmp(char *ori, char *pat)
{
get_next(pat);
int leno = strlen(ori), lenp = strlen(pat);
int k = 0;
while(k < leno && k < lenp && ori[k] == pat[k]) ++k;
extend[0] = k;
k = 0;
for(int i = 1; ori[i]; i++)
{
if(i + Next[i-k] < k + extend[k]) extend[i] = Next[i-k];
else
{
int j = max(k + extend[k] - i, 0);
while(i + j < leno && j < lenp && ori[i+j] == pat[j]) ++j;
extend[i] = j;
k = i;
}
}
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf(" %s", pat);
int lenp = strlen(pat);
for(int i = 0; i < lenp; i++) ori[i] = ori[i+lenp] = pat[i];
ori[lenp*2] = '\0';
extkmp(ori, pat);
int ansl = 0, anse = 1, ansg = 0;
for(int i = 1; i < lenp; i++)
{
if(extend[i] == lenp) break;
else
{
if(ori[i+extend[i]] > pat[extend[i]]) ansg++;
else ansl++;
}
}
printf("Case %d: %d %d %d\n", ++cas, ansl, anse, ansg);
}
return 0;
}