标签:子串 UVA10298 后缀 YBTOJ 最长 重复 text Strings getchar
题目大意:
求一个字符串由多少个重复的子串连接而成。
正文:
我们定义被重复的子串是 \(t\)。
如果最长前后缀的长度可以等于 \(n\),那么一段重复的字串,它的最长前后缀,肯定是 \(n\);如果必须小于 \(n\),则它的最长前后缀是 \(n-\text{len}(t)\)。
我们可以通过这个性质,先用 KMP 求出最长前后缀,可以算出被重复的子串长度,那么被循环次数就是 \(\frac{n}{n-\text{border}}\),其中 \(\text{border}\) 表示最长前后缀。如果式子不能整除,说明这个字符串没有被重复。
代码:
const int N = 1e6 + 10;
inline ll READ()
{
ll x = 0, f = 1;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x * f;
}
char s[N];
int nxt[N];
void KMP (char *s, int n, int op = 1)
{
int j = 0;
for (int i = op; i < n; i++)
{
while (j && s[i] != s[j]) j = nxt[j];
if (s[i] == s[j]) j++;
if(op) nxt[i + 1] = j;
else
{
if (j == n) {}
}
}
return;
}
int main()
{
for (scanf("%s", s); s[0] != '.'; scanf ("%s", s))
{
memset (nxt, 0, sizeof nxt);
int n = strlen(s);
KMP(s, n);
if (n % (n - nxt[n])) printf ("1\n");
else printf ("%d\n", n / (n - nxt[n]));
}
return 0;
}
标签:子串,UVA10298,后缀,YBTOJ,最长,重复,text,Strings,getchar 来源: https://www.cnblogs.com/GJY-JURUO/p/14731897.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。