第一题:Power Strings
题目链接:http://poj.org/problem?id=2406
题目大意:
给出一个字符串,求出这个字符串循环次数
思路:
用KMP算法求出字符串的next数组,next数组存的是当前这个字符上一次出现的位置,通过这个操作判断是否存在循环len%(len- next[len]),因为是判断整个字符串因此只需看最后一个的next数组就好。
代码:
<span style="font-size:18px;">#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int len;
int next[1000005];
char str[1000005];
void getnext()
{
next[0] = -1;
int i = 0, k = -1;
while(i < len)
{
if(k == -1 || str[k] == str[i])
{
i++;
k++;
next[i] = k;
}
else
k = next[k];
}
}
int main()
{
while(scanf("%s", str)!=EOF)
{
if(str[0] == '.')
break;
len = strlen(str);
getnext();
if(len%(len - next[len]) == 0)
{
printf("%d\n", len/(len - next[len]));
}
else
printf("1\n");
}
return 0;
}
</span>
第二题:Period
题目链接:http://poj.org/problem?id=1961
题目大意:给你一个字符串,求这个字符串到第i个字符为止的循环节的次数。
比如aabaabaabaab,长度为12.到第二个a时,a出现2次,输出2.到第二个b时,aab出现了2次,输出2.到第三个b时,aab出现3次,输出3.到第四个b时,aab出现4次,输出4.
思路:
用KMP算法求出字符串的循环节,之后用for循环遍历字符串,找到这个位置next数组不为0并且用i%(i- next[i])==0 判断之前有循环的。
代码:
<span style="font-size:18px;">#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int len;
int next[1000005];
char str[1000005];
void getnext()
{
next[0] = -1;
int i = 0, k = -1;
while(i < len)
{
if(k == -1 || str[k] == str[i])
{
i++;
k++;
next[i] = k;
}
else
k = next[k];
}
}
int main()
{
int t = 1;
while(scanf("%d", &len)==1 && len)
{
getchar();
gets(str);
getnext();
printf("Test case #%d\n", t++);
for(int i = 2; i <= len; i++)
{
if(next[i] != 0 && i%(i - next[i])==0)
printf("%d %d\n", i, i/(i-next[i]));
}
printf("\n");
}
return 0;
}</span>
题目链接:http://poj.org/problem?id=2752
题目大意:
求对于一个字符串满足前n个字符全等于后n个字符的n有哪些,输出位置和长度
思路:
用KMP算法处理字符串,得出它的循环节,之后再从字符串尾部开始判断next, 必须从尾部,因为要判断整个字符串的后缀,注意格式,这一篇能够更好地理解next数组的含义
代码:
<span style="font-size:18px;">#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int len;
int next[1000005];
char str[1000005];
int ans [1000005];
void getnext()
{
next[0] = -1;
int i = 0, k = -1;
while(i < len)
{
if(k == -1 || str[k] == str[i])
{
i++;
k++;
next[i] = k;
}
else
k = next[k];
}
}
int main()
{
while(scanf("%s", str)!=EOF)
{
int k = 1;
len = strlen(str);
getnext();
ans[0] = len;
int j = len;
while(next[j] > 0)
{
ans[k++] = next[j];
j= next[j];
}
for(int j = k-1; j>=0; j--)
{
printf("%d", ans[j]);
if(j+1)
printf(" ");
}
printf("\n");
}
return 0;
}</span>